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(3D_CANVAS)
     29 
     30 #include "WebGLRenderingContext.h"
     31 
     32 #include "CanvasPixelArray.h"
     33 #include "HTMLCanvasElement.h"
     34 #include "HTMLImageElement.h"
     35 #include "ImageBuffer.h"
     36 #include "ImageData.h"
     37 #include "NotImplemented.h"
     38 #include "RenderBox.h"
     39 #include "RenderLayer.h"
     40 #include "WebGLActiveInfo.h"
     41 #include "WebGLBuffer.h"
     42 #include "WebGLContextAttributes.h"
     43 #include "WebGLFramebuffer.h"
     44 #include "WebGLProgram.h"
     45 #include "WebGLRenderbuffer.h"
     46 #include "WebGLTexture.h"
     47 #include "WebGLShader.h"
     48 #include "WebGLUniformLocation.h"
     49 #include "HTMLCanvasElement.h"
     50 #include "HTMLImageElement.h"
     51 #include "ImageBuffer.h"
     52 #include "NotImplemented.h"
     53 #include "RenderBox.h"
     54 #include "RenderLayer.h"
     55 
     56 #include <wtf/ByteArray.h>
     57 
     58 namespace WebCore {
     59 
     60 class WebGLStateRestorer {
     61 public:
     62     WebGLStateRestorer(WebGLRenderingContext* context,
     63                        bool changed)
     64         : m_context(context)
     65         , m_changed(changed)
     66     {
     67     }
     68 
     69     ~WebGLStateRestorer()
     70     {
     71         m_context->cleanupAfterGraphicsCall(m_changed);
     72     }
     73 
     74 private:
     75     WebGLRenderingContext* m_context;
     76     bool m_changed;
     77 };
     78 
     79 PassOwnPtr<WebGLRenderingContext> WebGLRenderingContext::create(HTMLCanvasElement* canvas, WebGLContextAttributes* attrs)
     80 {
     81     OwnPtr<GraphicsContext3D> context(GraphicsContext3D::create(attrs->attributes()));
     82     if (!context)
     83         return 0;
     84 
     85     return new WebGLRenderingContext(canvas, context.release());
     86 }
     87 
     88 WebGLRenderingContext::WebGLRenderingContext(HTMLCanvasElement* passedCanvas, PassOwnPtr<GraphicsContext3D> context)
     89     : CanvasRenderingContext(passedCanvas)
     90     , m_context(context)
     91     , m_needsUpdate(true)
     92     , m_markedCanvasDirty(false)
     93     , m_activeTextureUnit(0)
     94 {
     95     ASSERT(m_context);
     96     int numVertexAttribs = 0;
     97     m_context->getIntegerv(GraphicsContext3D::MAX_VERTEX_ATTRIBS, &numVertexAttribs);
     98     m_maxVertexAttribs = numVertexAttribs;
     99     m_context->reshape(canvas()->width(), canvas()->height());
    100 }
    101 
    102 WebGLRenderingContext::~WebGLRenderingContext()
    103 {
    104     detachAndRemoveAllObjects();
    105 }
    106 
    107 void WebGLRenderingContext::markContextChanged()
    108 {
    109 #if USE(ACCELERATED_COMPOSITING)
    110     if (canvas()->renderBox() && canvas()->renderBox()->hasLayer()) {
    111         canvas()->renderBox()->layer()->rendererContentChanged();
    112     } else {
    113 #endif
    114         if (!m_markedCanvasDirty) {
    115             // Make sure the canvas's image buffer is allocated.
    116             canvas()->buffer();
    117             canvas()->willDraw(FloatRect(0, 0, canvas()->width(), canvas()->height()));
    118             m_markedCanvasDirty = true;
    119         }
    120 #if USE(ACCELERATED_COMPOSITING)
    121     }
    122 #endif
    123 }
    124 
    125 void WebGLRenderingContext::beginPaint()
    126 {
    127     if (m_markedCanvasDirty) {
    128         m_context->beginPaint(this);
    129     }
    130 }
    131 
    132 void WebGLRenderingContext::endPaint()
    133 {
    134     if (m_markedCanvasDirty) {
    135         m_markedCanvasDirty = false;
    136         m_context->endPaint();
    137     }
    138 }
    139 
    140 void WebGLRenderingContext::reshape(int width, int height)
    141 {
    142     if (m_needsUpdate) {
    143 #if USE(ACCELERATED_COMPOSITING)
    144         if (canvas()->renderBox() && canvas()->renderBox()->hasLayer())
    145             canvas()->renderBox()->layer()->rendererContentChanged();
    146 #endif
    147         m_needsUpdate = false;
    148     }
    149 
    150     m_context->reshape(width, height);
    151 }
    152 
    153 int WebGLRenderingContext::sizeInBytes(int type, ExceptionCode& ec)
    154 {
    155     UNUSED_PARAM(ec);
    156     int result = m_context->sizeInBytes(type);
    157     if (result <= 0)
    158         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
    159 
    160     return result;
    161 }
    162 
    163 void WebGLRenderingContext::activeTexture(unsigned long texture, ExceptionCode& ec)
    164 {
    165     UNUSED_PARAM(ec);
    166     if ((texture - GraphicsContext3D::TEXTURE0) > sizeof(m_textureUnits) / sizeof(TextureUnitState)) {
    167         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
    168         return;
    169     }
    170     m_activeTextureUnit = texture - GraphicsContext3D::TEXTURE0;
    171     m_context->activeTexture(texture);
    172     cleanupAfterGraphicsCall(false);
    173 }
    174 
    175 void WebGLRenderingContext::attachShader(WebGLProgram* program, WebGLShader* shader, ExceptionCode& ec)
    176 {
    177     UNUSED_PARAM(ec);
    178     if (!program || program->context() != this || !shader || shader->context() != this) {
    179         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
    180         return;
    181     }
    182     m_context->attachShader(program, shader);
    183     cleanupAfterGraphicsCall(false);
    184 }
    185 
    186 void WebGLRenderingContext::bindAttribLocation(WebGLProgram* program, unsigned long index, const String& name, ExceptionCode& ec)
    187 {
    188     UNUSED_PARAM(ec);
    189     if (!program || program->context() != this) {
    190         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
    191         return;
    192     }
    193     m_context->bindAttribLocation(program, index, name);
    194     cleanupAfterGraphicsCall(false);
    195 }
    196 
    197 void WebGLRenderingContext::bindBuffer(unsigned long target, WebGLBuffer* buffer, ExceptionCode& ec)
    198 {
    199     UNUSED_PARAM(ec);
    200     if (buffer && buffer->context() != this) {
    201         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
    202         return;
    203     }
    204 
    205     if (target == GraphicsContext3D::ARRAY_BUFFER)
    206         m_boundArrayBuffer = buffer;
    207     else if (target == GraphicsContext3D::ELEMENT_ARRAY_BUFFER)
    208         m_boundElementArrayBuffer = buffer;
    209     else {
    210         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
    211         return;
    212     }
    213 
    214     m_context->bindBuffer(target, buffer);
    215     cleanupAfterGraphicsCall(false);
    216 }
    217 
    218 
    219 void WebGLRenderingContext::bindFramebuffer(unsigned long target, WebGLFramebuffer* buffer, ExceptionCode& ec)
    220 {
    221     UNUSED_PARAM(ec);
    222     if (buffer && buffer->context() != this) {
    223         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
    224         return;
    225     }
    226     if (target != GraphicsContext3D::FRAMEBUFFER) {
    227         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
    228         return;
    229     }
    230     m_framebufferBinding = buffer;
    231     m_context->bindFramebuffer(target, buffer);
    232     cleanupAfterGraphicsCall(false);
    233 }
    234 
    235 void WebGLRenderingContext::bindRenderbuffer(unsigned long target, WebGLRenderbuffer* renderBuffer, ExceptionCode& ec)
    236 {
    237     UNUSED_PARAM(ec);
    238     if (renderBuffer && renderBuffer->context() != this) {
    239         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
    240         return;
    241     }
    242     if (target != GraphicsContext3D::RENDERBUFFER) {
    243         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
    244         return;
    245     }
    246     m_renderbufferBinding = renderBuffer;
    247     m_context->bindRenderbuffer(target, renderBuffer);
    248     cleanupAfterGraphicsCall(false);
    249 }
    250 
    251 
    252 void WebGLRenderingContext::bindTexture(unsigned long target, WebGLTexture* texture, ExceptionCode& ec)
    253 {
    254     UNUSED_PARAM(ec);
    255     if (texture && texture->context() != this) {
    256         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
    257         return;
    258     }
    259     if (target == GraphicsContext3D::TEXTURE_2D)
    260         m_textureUnits[m_activeTextureUnit].m_texture2DBinding = texture;
    261     else if (target == GraphicsContext3D::TEXTURE_CUBE_MAP)
    262         m_textureUnits[m_activeTextureUnit].m_textureCubeMapBinding = texture;
    263     else {
    264         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
    265         return;
    266     }
    267     m_context->bindTexture(target, texture);
    268     cleanupAfterGraphicsCall(false);
    269 }
    270 
    271 void WebGLRenderingContext::blendColor(double red, double green, double blue, double alpha)
    272 {
    273     m_context->blendColor(red, green, blue, alpha);
    274     cleanupAfterGraphicsCall(false);
    275 }
    276 
    277 void WebGLRenderingContext::blendEquation( unsigned long mode )
    278 {
    279     m_context->blendEquation(mode);
    280     cleanupAfterGraphicsCall(false);
    281 }
    282 
    283 void WebGLRenderingContext::blendEquationSeparate(unsigned long modeRGB, unsigned long modeAlpha)
    284 {
    285     m_context->blendEquationSeparate(modeRGB, modeAlpha);
    286     cleanupAfterGraphicsCall(false);
    287 }
    288 
    289 
    290 void WebGLRenderingContext::blendFunc(unsigned long sfactor, unsigned long dfactor)
    291 {
    292     m_context->blendFunc(sfactor, dfactor);
    293     cleanupAfterGraphicsCall(false);
    294 }
    295 
    296 void WebGLRenderingContext::blendFuncSeparate(unsigned long srcRGB, unsigned long dstRGB, unsigned long srcAlpha, unsigned long dstAlpha)
    297 {
    298     m_context->blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha);
    299     cleanupAfterGraphicsCall(false);
    300 }
    301 
    302 void WebGLRenderingContext::bufferData(unsigned long target, int size, unsigned long usage, ExceptionCode& ec)
    303 {
    304     UNUSED_PARAM(ec);
    305     if (target == GraphicsContext3D::ELEMENT_ARRAY_BUFFER && m_boundElementArrayBuffer) {
    306         if (!m_boundElementArrayBuffer->associateBufferData(target, size)) {
    307             m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
    308             return;
    309         }
    310     } else if (target == GraphicsContext3D::ARRAY_BUFFER && m_boundArrayBuffer) {
    311         if (!m_boundArrayBuffer->associateBufferData(target, size)) {
    312             m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
    313             return;
    314         }
    315     } else {
    316         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
    317         return;
    318     }
    319 
    320     m_context->bufferData(target, size, usage);
    321     cleanupAfterGraphicsCall(false);
    322 }
    323 
    324 void WebGLRenderingContext::bufferData(unsigned long target, WebGLArray* data, unsigned long usage, ExceptionCode& ec)
    325 {
    326     UNUSED_PARAM(ec);
    327     if (target == GraphicsContext3D::ELEMENT_ARRAY_BUFFER && m_boundElementArrayBuffer) {
    328         if (!m_boundElementArrayBuffer->associateBufferData(target, data)) {
    329             m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
    330             return;
    331         }
    332     } else if (target == GraphicsContext3D::ARRAY_BUFFER && m_boundArrayBuffer) {
    333         if (!m_boundArrayBuffer->associateBufferData(target, data)) {
    334             m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
    335             return;
    336         }
    337     } else {
    338         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
    339         return;
    340     }
    341 
    342     m_context->bufferData(target, data, usage);
    343     cleanupAfterGraphicsCall(false);
    344 }
    345 
    346 void WebGLRenderingContext::bufferSubData(unsigned long target, long offset, WebGLArray* data, ExceptionCode& ec)
    347 {
    348     UNUSED_PARAM(ec);
    349     if (target == GraphicsContext3D::ELEMENT_ARRAY_BUFFER && m_boundElementArrayBuffer) {
    350         if (!m_boundElementArrayBuffer->associateBufferSubData(target, offset, data)) {
    351             m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
    352             return;
    353         }
    354     } else if (target == GraphicsContext3D::ARRAY_BUFFER && m_boundArrayBuffer) {
    355         if (!m_boundArrayBuffer->associateBufferSubData(target, offset, data)) {
    356             m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
    357             return;
    358         }
    359     } else {
    360         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
    361         return;
    362     }
    363 
    364     m_context->bufferSubData(target, offset, data);
    365     cleanupAfterGraphicsCall(false);
    366 }
    367 
    368 unsigned long WebGLRenderingContext::checkFramebufferStatus(unsigned long target)
    369 {
    370     return m_context->checkFramebufferStatus(target);
    371     cleanupAfterGraphicsCall(false);
    372 }
    373 
    374 void WebGLRenderingContext::clear(unsigned long mask)
    375 {
    376     m_context->clear(mask);
    377     cleanupAfterGraphicsCall(true);
    378 }
    379 
    380 void WebGLRenderingContext::clearColor(double r, double g, double b, double a)
    381 {
    382     if (isnan(r))
    383         r = 0;
    384     if (isnan(g))
    385         g = 0;
    386     if (isnan(b))
    387         b = 0;
    388     if (isnan(a))
    389         a = 1;
    390     m_context->clearColor(r, g, b, a);
    391     cleanupAfterGraphicsCall(false);
    392 }
    393 
    394 void WebGLRenderingContext::clearDepth(double depth)
    395 {
    396     m_context->clearDepth(depth);
    397     cleanupAfterGraphicsCall(false);
    398 }
    399 
    400 void WebGLRenderingContext::clearStencil(long s)
    401 {
    402     m_context->clearStencil(s);
    403     cleanupAfterGraphicsCall(false);
    404 }
    405 
    406 void WebGLRenderingContext::colorMask(bool red, bool green, bool blue, bool alpha)
    407 {
    408     m_context->colorMask(red, green, blue, alpha);
    409     cleanupAfterGraphicsCall(false);
    410 }
    411 
    412 void WebGLRenderingContext::compileShader(WebGLShader* shader, ExceptionCode& ec)
    413 {
    414     UNUSED_PARAM(ec);
    415     if (!shader || shader->context() != this) {
    416         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
    417         return;
    418     }
    419     m_context->compileShader(shader);
    420     cleanupAfterGraphicsCall(false);
    421 }
    422 
    423 void WebGLRenderingContext::copyTexImage2D(unsigned long target, long level, unsigned long internalformat, long x, long y, unsigned long width, unsigned long height, long border)
    424 {
    425     m_context->copyTexImage2D(target, level, internalformat, x, y, width, height, border);
    426     cleanupAfterGraphicsCall(false);
    427 }
    428 
    429 void WebGLRenderingContext::copyTexSubImage2D(unsigned long target, long level, long xoffset, long yoffset, long x, long y, unsigned long width, unsigned long height)
    430 {
    431     m_context->copyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height);
    432     cleanupAfterGraphicsCall(false);
    433 }
    434 
    435 PassRefPtr<WebGLBuffer> WebGLRenderingContext::createBuffer()
    436 {
    437     RefPtr<WebGLBuffer> o = WebGLBuffer::create(this);
    438     addObject(o.get());
    439     return o;
    440 }
    441 
    442 PassRefPtr<WebGLFramebuffer> WebGLRenderingContext::createFramebuffer()
    443 {
    444     RefPtr<WebGLFramebuffer> o = WebGLFramebuffer::create(this);
    445     addObject(o.get());
    446     return o;
    447 }
    448 
    449 PassRefPtr<WebGLTexture> WebGLRenderingContext::createTexture()
    450 {
    451     RefPtr<WebGLTexture> o = WebGLTexture::create(this);
    452     addObject(o.get());
    453     return o;
    454 }
    455 
    456 PassRefPtr<WebGLProgram> WebGLRenderingContext::createProgram()
    457 {
    458     RefPtr<WebGLProgram> o = WebGLProgram::create(this);
    459     addObject(o.get());
    460     return o;
    461 }
    462 
    463 PassRefPtr<WebGLRenderbuffer> WebGLRenderingContext::createRenderbuffer()
    464 {
    465     RefPtr<WebGLRenderbuffer> o = WebGLRenderbuffer::create(this);
    466     addObject(o.get());
    467     return o;
    468 }
    469 
    470 PassRefPtr<WebGLShader> WebGLRenderingContext::createShader(unsigned long type, ExceptionCode& ec)
    471 {
    472     UNUSED_PARAM(ec);
    473     if (type != GraphicsContext3D::VERTEX_SHADER && type != GraphicsContext3D::FRAGMENT_SHADER) {
    474         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
    475         return 0;
    476     }
    477 
    478     RefPtr<WebGLShader> o = WebGLShader::create(this, static_cast<GraphicsContext3D::WebGLEnumType>(type));
    479     addObject(o.get());
    480     return o;
    481 }
    482 
    483 void WebGLRenderingContext::cullFace(unsigned long mode)
    484 {
    485     m_context->cullFace(mode);
    486     cleanupAfterGraphicsCall(false);
    487 }
    488 
    489 void WebGLRenderingContext::deleteBuffer(WebGLBuffer* buffer)
    490 {
    491     if (!buffer)
    492         return;
    493 
    494     buffer->deleteObject();
    495 }
    496 
    497 void WebGLRenderingContext::deleteFramebuffer(WebGLFramebuffer* framebuffer)
    498 {
    499     if (!framebuffer)
    500         return;
    501 
    502     framebuffer->deleteObject();
    503 }
    504 
    505 void WebGLRenderingContext::deleteProgram(WebGLProgram* program)
    506 {
    507     if (!program)
    508         return;
    509 
    510     program->deleteObject();
    511 }
    512 
    513 void WebGLRenderingContext::deleteRenderbuffer(WebGLRenderbuffer* renderbuffer)
    514 {
    515     if (!renderbuffer)
    516         return;
    517 
    518     renderbuffer->deleteObject();
    519 }
    520 
    521 void WebGLRenderingContext::deleteShader(WebGLShader* shader)
    522 {
    523     if (!shader)
    524         return;
    525 
    526     shader->deleteObject();
    527 }
    528 
    529 void WebGLRenderingContext::deleteTexture(WebGLTexture* texture)
    530 {
    531     if (!texture)
    532         return;
    533 
    534     texture->deleteObject();
    535 }
    536 
    537 void WebGLRenderingContext::depthFunc(unsigned long func)
    538 {
    539     m_context->depthFunc(func);
    540     cleanupAfterGraphicsCall(false);
    541 }
    542 
    543 void WebGLRenderingContext::depthMask(bool flag)
    544 {
    545     m_context->depthMask(flag);
    546     cleanupAfterGraphicsCall(false);
    547 }
    548 
    549 void WebGLRenderingContext::depthRange(double zNear, double zFar)
    550 {
    551     m_context->depthRange(zNear, zFar);
    552     cleanupAfterGraphicsCall(false);
    553 }
    554 
    555 void WebGLRenderingContext::detachShader(WebGLProgram* program, WebGLShader* shader, ExceptionCode& ec)
    556 {
    557     UNUSED_PARAM(ec);
    558     if (!program || program->context() != this || !shader || shader->context() != this) {
    559         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
    560         return;
    561     }
    562     m_context->detachShader(program, shader);
    563     cleanupAfterGraphicsCall(false);
    564 }
    565 
    566 
    567 void WebGLRenderingContext::disable(unsigned long cap)
    568 {
    569     m_context->disable(cap);
    570     cleanupAfterGraphicsCall(false);
    571 }
    572 
    573 void WebGLRenderingContext::disableVertexAttribArray(unsigned long index, ExceptionCode& ec)
    574 {
    575     UNUSED_PARAM(ec);
    576     if (index >= m_maxVertexAttribs) {
    577         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
    578         return;
    579     }
    580 
    581     if (index < m_vertexAttribState.size())
    582         m_vertexAttribState[index].enabled = false;
    583 
    584     m_context->disableVertexAttribArray(index);
    585     cleanupAfterGraphicsCall(false);
    586 }
    587 
    588 bool WebGLRenderingContext::validateElementArraySize(unsigned long count, unsigned long type, long offset)
    589 {
    590     if (!m_boundElementArrayBuffer)
    591         return false;
    592 
    593     if (offset < 0)
    594         return false;
    595 
    596     unsigned long uoffset = static_cast<unsigned long>(offset);
    597 
    598     if (type == GraphicsContext3D::UNSIGNED_SHORT) {
    599         // For an unsigned short array, offset must be divisible by 2 for alignment reasons.
    600         if (uoffset & 1)
    601             return false;
    602 
    603         // Make uoffset an element offset.
    604         uoffset /= 2;
    605 
    606         unsigned long n = m_boundElementArrayBuffer->byteLength(GraphicsContext3D::ELEMENT_ARRAY_BUFFER) / 2;
    607         if (uoffset > n || count > n - uoffset)
    608             return false;
    609     } else if (type == GraphicsContext3D::UNSIGNED_BYTE) {
    610         unsigned long n = m_boundElementArrayBuffer->byteLength(GraphicsContext3D::ELEMENT_ARRAY_BUFFER);
    611         if (uoffset > n || count > n - uoffset)
    612             return false;
    613     }
    614     return true;
    615 }
    616 
    617 bool WebGLRenderingContext::validateIndexArrayConservative(unsigned long type, long& numElementsRequired)
    618 {
    619     // Performs conservative validation by caching a maximum index of
    620     // the given type per element array buffer. If all of the bound
    621     // array buffers have enough elements to satisfy that maximum
    622     // index, skips the expensive per-draw-call iteration in
    623     // validateIndexArrayPrecise.
    624 
    625     long maxIndex = m_boundElementArrayBuffer->getCachedMaxIndex(type);
    626     if (maxIndex < 0) {
    627         // Compute the maximum index in the entire buffer for the given type of index.
    628         switch (type) {
    629         case GraphicsContext3D::UNSIGNED_BYTE: {
    630             unsigned numElements = m_boundElementArrayBuffer->byteLength(GraphicsContext3D::ELEMENT_ARRAY_BUFFER);
    631             const unsigned char* p = static_cast<const unsigned char*>(m_boundElementArrayBuffer->elementArrayBuffer()->data());
    632             for (unsigned i = 0; i < numElements; i++)
    633                 maxIndex = max(maxIndex, static_cast<long>(p[i]));
    634             break;
    635         }
    636         case GraphicsContext3D::UNSIGNED_SHORT: {
    637             unsigned numElements = m_boundElementArrayBuffer->byteLength(GraphicsContext3D::ELEMENT_ARRAY_BUFFER) / sizeof(unsigned short);
    638             const unsigned short* p = static_cast<const unsigned short*>(m_boundElementArrayBuffer->elementArrayBuffer()->data());
    639             for (unsigned i = 0; i < numElements; i++)
    640                 maxIndex = max(maxIndex, static_cast<long>(p[i]));
    641             break;
    642         }
    643         default:
    644             return false;
    645         }
    646         m_boundElementArrayBuffer->setCachedMaxIndex(type, maxIndex);
    647     }
    648 
    649     if (maxIndex >= 0) {
    650         // The number of required elements is one more than the maximum
    651         // index that will be accessed.
    652         numElementsRequired = maxIndex + 1;
    653         return true;
    654     }
    655 
    656     return false;
    657 }
    658 
    659 bool WebGLRenderingContext::validateIndexArrayPrecise(unsigned long count, unsigned long type, long offset, long& numElementsRequired)
    660 {
    661     long lastIndex = -1;
    662 
    663     if (!m_boundElementArrayBuffer)
    664         return false;
    665 
    666     unsigned long uoffset = static_cast<unsigned long>(offset);
    667     unsigned long n = count;
    668 
    669     if (type == GraphicsContext3D::UNSIGNED_SHORT) {
    670         // Make uoffset an element offset.
    671         uoffset /= 2;
    672         const unsigned short* p = static_cast<const unsigned short*>(m_boundElementArrayBuffer->elementArrayBuffer()->data()) + uoffset;
    673         while (n-- > 0) {
    674             if (*p > lastIndex)
    675                 lastIndex = *p;
    676             ++p;
    677         }
    678     } else if (type == GraphicsContext3D::UNSIGNED_BYTE) {
    679         const unsigned char* p = static_cast<const unsigned char*>(m_boundElementArrayBuffer->elementArrayBuffer()->data()) + uoffset;
    680         while (n-- > 0) {
    681             if (*p > lastIndex)
    682                 lastIndex = *p;
    683             ++p;
    684         }
    685     }
    686 
    687     // Then set the last index in the index array and make sure it is valid.
    688     numElementsRequired = lastIndex + 1;
    689     return numElementsRequired > 0;
    690 }
    691 
    692 bool WebGLRenderingContext::validateRenderingState(long numElementsRequired)
    693 {
    694     // Look in each enabled vertex attrib and find the smallest buffer size
    695     long smallestNumElements = LONG_MAX;
    696     for (unsigned i = 0; i < m_vertexAttribState.size(); ++i) {
    697         const VertexAttribState& state = m_vertexAttribState[i];
    698         if (state.enabled && state.numElements < smallestNumElements)
    699             smallestNumElements = state.numElements;
    700     }
    701 
    702     if (smallestNumElements == LONG_MAX)
    703         smallestNumElements = 0;
    704 
    705     return numElementsRequired <= smallestNumElements;
    706 }
    707 
    708 void WebGLRenderingContext::drawArrays(unsigned long mode, long first, long count, ExceptionCode& ec)
    709 {
    710     UNUSED_PARAM(ec);
    711     // Ensure we have a valid rendering state
    712     if (first < 0 || count < 0 || !validateRenderingState(first + count)) {
    713         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
    714         return;
    715     }
    716 
    717     m_context->drawArrays(mode, first, count);
    718     cleanupAfterGraphicsCall(true);
    719 }
    720 
    721 void WebGLRenderingContext::drawElements(unsigned long mode, unsigned long count, unsigned long type, long offset, ExceptionCode& ec)
    722 {
    723     UNUSED_PARAM(ec);
    724     // Ensure we have a valid rendering state
    725     long numElements;
    726 
    727     if (offset < 0 || !validateElementArraySize(count, type, offset)) {
    728         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
    729         return;
    730     }
    731 
    732     if (!validateIndexArrayConservative(type, numElements) || !validateRenderingState(numElements))
    733         if (!validateIndexArrayPrecise(count, type, offset, numElements) || !validateRenderingState(numElements)) {
    734             m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
    735             return;
    736         }
    737 
    738     m_context->drawElements(mode, count, type, offset);
    739     cleanupAfterGraphicsCall(true);
    740 }
    741 
    742 void WebGLRenderingContext::enable(unsigned long cap)
    743 {
    744     m_context->enable(cap);
    745     cleanupAfterGraphicsCall(false);
    746 }
    747 
    748 void WebGLRenderingContext::enableVertexAttribArray(unsigned long index, ExceptionCode& ec)
    749 {
    750     UNUSED_PARAM(ec);
    751     if (index >= m_maxVertexAttribs) {
    752         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
    753         return;
    754     }
    755 
    756     if (index >= m_vertexAttribState.size())
    757         m_vertexAttribState.resize(index + 1);
    758 
    759     m_vertexAttribState[index].enabled = true;
    760 
    761     m_context->enableVertexAttribArray(index);
    762     cleanupAfterGraphicsCall(false);
    763 }
    764 
    765 void WebGLRenderingContext::finish()
    766 {
    767     m_context->finish();
    768     cleanupAfterGraphicsCall(true);
    769 }
    770 
    771 
    772 void WebGLRenderingContext::flush()
    773 {
    774     m_context->flush();
    775     cleanupAfterGraphicsCall(true);
    776 }
    777 
    778 void WebGLRenderingContext::framebufferRenderbuffer(unsigned long target, unsigned long attachment, unsigned long renderbuffertarget, WebGLRenderbuffer* buffer, ExceptionCode& ec)
    779 {
    780     UNUSED_PARAM(ec);
    781     if (buffer && buffer->context() != this) {
    782         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
    783         return;
    784     }
    785     // Don't allow the default framebuffer to be mutated; all current
    786     // implementations use an FBO internally in place of the default
    787     // FBO.
    788     if (!m_framebufferBinding || !m_framebufferBinding->object()) {
    789         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
    790         return;
    791     }
    792     m_context->framebufferRenderbuffer(target, attachment, renderbuffertarget, buffer);
    793     cleanupAfterGraphicsCall(false);
    794 }
    795 
    796 void WebGLRenderingContext::framebufferTexture2D(unsigned long target, unsigned long attachment, unsigned long textarget, WebGLTexture* texture, long level, ExceptionCode& ec)
    797 {
    798     UNUSED_PARAM(ec);
    799     if (texture && texture->context() != this) {
    800         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
    801         return;
    802     }
    803     // Don't allow the default framebuffer to be mutated; all current
    804     // implementations use an FBO internally in place of the default
    805     // FBO.
    806     if (!m_framebufferBinding || !m_framebufferBinding->object()) {
    807         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
    808         return;
    809     }
    810     m_context->framebufferTexture2D(target, attachment, textarget, texture, level);
    811     cleanupAfterGraphicsCall(false);
    812 }
    813 
    814 void WebGLRenderingContext::frontFace(unsigned long mode)
    815 {
    816     m_context->frontFace(mode);
    817     cleanupAfterGraphicsCall(false);
    818 }
    819 
    820 void WebGLRenderingContext::generateMipmap(unsigned long target)
    821 {
    822     m_context->generateMipmap(target);
    823     cleanupAfterGraphicsCall(false);
    824 }
    825 
    826 PassRefPtr<WebGLActiveInfo> WebGLRenderingContext::getActiveAttrib(WebGLProgram* program, unsigned long index, ExceptionCode& ec)
    827 {
    828     UNUSED_PARAM(ec);
    829     ActiveInfo info;
    830     if (!program || program->context() != this) {
    831         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
    832         return 0;
    833     }
    834     if (!m_context->getActiveAttrib(program, index, info)) {
    835         return 0;
    836     }
    837     return WebGLActiveInfo::create(info.name, info.type, info.size);
    838 }
    839 
    840 PassRefPtr<WebGLActiveInfo> WebGLRenderingContext::getActiveUniform(WebGLProgram* program, unsigned long index, ExceptionCode& ec)
    841 {
    842     UNUSED_PARAM(ec);
    843     ActiveInfo info;
    844     if (!program || program->context() != this) {
    845         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
    846         return 0;
    847     }
    848     if (!m_context->getActiveUniform(program, index, info)) {
    849         return 0;
    850     }
    851     return WebGLActiveInfo::create(info.name, info.type, info.size);
    852 }
    853 
    854 int WebGLRenderingContext::getAttribLocation(WebGLProgram* program, const String& name)
    855 {
    856     return m_context->getAttribLocation(program, name);
    857 }
    858 
    859 WebGLGetInfo WebGLRenderingContext::getBufferParameter(unsigned long target, unsigned long pname, ExceptionCode& ec)
    860 {
    861     UNUSED_PARAM(ec);
    862     if (target != GraphicsContext3D::ARRAY_BUFFER && target != GraphicsContext3D::ELEMENT_ARRAY_BUFFER) {
    863         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
    864         return WebGLGetInfo();
    865     }
    866 
    867     if (pname != GraphicsContext3D::BUFFER_SIZE && pname != GraphicsContext3D::BUFFER_USAGE) {
    868         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
    869         return WebGLGetInfo();
    870     }
    871 
    872     WebGLStateRestorer(this, false);
    873     int value;
    874     m_context->getBufferParameteriv(target, pname, &value);
    875     if (pname == GraphicsContext3D::BUFFER_SIZE)
    876         return WebGLGetInfo(static_cast<long>(value));
    877     else
    878         return WebGLGetInfo(static_cast<unsigned long>(value));
    879 }
    880 
    881 PassRefPtr<WebGLContextAttributes> WebGLRenderingContext::getContextAttributes()
    882 {
    883     // We always need to return a new WebGLContextAttributes object to
    884     // prevent the user from mutating any cached version.
    885     return WebGLContextAttributes::create(m_context->getContextAttributes());
    886 }
    887 
    888 unsigned long WebGLRenderingContext::getError()
    889 {
    890     return m_context->getError();
    891 }
    892 
    893 WebGLGetInfo WebGLRenderingContext::getFramebufferAttachmentParameter(unsigned long target, unsigned long attachment, unsigned long pname, ExceptionCode& ec)
    894 {
    895     UNUSED_PARAM(ec);
    896     if (target != GraphicsContext3D::FRAMEBUFFER
    897         || (attachment != GraphicsContext3D::COLOR_ATTACHMENT0
    898             && attachment != GraphicsContext3D::DEPTH_ATTACHMENT
    899             && attachment != GraphicsContext3D::STENCIL_ATTACHMENT)
    900         || (pname != GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
    901             && pname != GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_OBJECT_NAME
    902             && pname != GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL
    903             && pname != GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE)) {
    904         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
    905         return WebGLGetInfo();
    906     }
    907 
    908     if (pname != GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_OBJECT_NAME) {
    909         WebGLStateRestorer(this, false);
    910         int value;
    911         m_context->getFramebufferAttachmentParameteriv(target, attachment, pname, &value);
    912         if (pname == GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE)
    913             return WebGLGetInfo(static_cast<unsigned long>(value));
    914         else
    915             return WebGLGetInfo(static_cast<long>(value));
    916     } else {
    917         WebGLStateRestorer(this, false);
    918         int type = 0;
    919         m_context->getFramebufferAttachmentParameteriv(target, attachment, GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &type);
    920         int value = 0;
    921         m_context->getFramebufferAttachmentParameteriv(target, attachment, GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, &value);
    922         // FIXME: should consider canonicalizing these objects
    923         switch (type) {
    924         case GraphicsContext3D::RENDERBUFFER: {
    925             RefPtr<WebGLRenderbuffer> tmp = WebGLRenderbuffer::create(this, value);
    926             addObject(tmp.get());
    927             return WebGLGetInfo(PassRefPtr<WebGLRenderbuffer>(tmp));
    928         }
    929         case GraphicsContext3D::TEXTURE: {
    930             RefPtr<WebGLTexture> tmp = WebGLTexture::create(this, value);
    931             addObject(tmp.get());
    932             return WebGLGetInfo(PassRefPtr<WebGLTexture>(tmp));
    933         }
    934         default:
    935             // FIXME: raise exception?
    936             return WebGLGetInfo();
    937         }
    938     }
    939 }
    940 
    941 WebGLGetInfo WebGLRenderingContext::getParameter(unsigned long pname, ExceptionCode& ec)
    942 {
    943     UNUSED_PARAM(ec);
    944     WebGLStateRestorer(this, false);
    945     switch (pname) {
    946     case GraphicsContext3D::ACTIVE_TEXTURE:
    947         return getUnsignedLongParameter(pname);
    948     case GraphicsContext3D::ALIASED_LINE_WIDTH_RANGE:
    949         return getWebGLFloatArrayParameter(pname);
    950     case GraphicsContext3D::ALIASED_POINT_SIZE_RANGE:
    951         return getWebGLFloatArrayParameter(pname);
    952     case GraphicsContext3D::ALPHA_BITS:
    953         return getLongParameter(pname);
    954     case GraphicsContext3D::ARRAY_BUFFER_BINDING:
    955         return WebGLGetInfo(PassRefPtr<WebGLBuffer>(m_boundArrayBuffer));
    956     case GraphicsContext3D::BLEND:
    957         return getBooleanParameter(pname);
    958     case GraphicsContext3D::BLEND_COLOR:
    959         return getWebGLFloatArrayParameter(pname);
    960     case GraphicsContext3D::BLEND_DST_ALPHA:
    961         return getUnsignedLongParameter(pname);
    962     case GraphicsContext3D::BLEND_DST_RGB:
    963         return getUnsignedLongParameter(pname);
    964     case GraphicsContext3D::BLEND_EQUATION_ALPHA:
    965         return getUnsignedLongParameter(pname);
    966     case GraphicsContext3D::BLEND_EQUATION_RGB:
    967         return getUnsignedLongParameter(pname);
    968     case GraphicsContext3D::BLEND_SRC_ALPHA:
    969         return getUnsignedLongParameter(pname);
    970     case GraphicsContext3D::BLEND_SRC_RGB:
    971         return getUnsignedLongParameter(pname);
    972     case GraphicsContext3D::BLUE_BITS:
    973         return getLongParameter(pname);
    974     case GraphicsContext3D::COLOR_CLEAR_VALUE:
    975         return getWebGLFloatArrayParameter(pname);
    976     case GraphicsContext3D::COLOR_WRITEMASK:
    977         return getWebGLUnsignedByteArrayParameter(pname);
    978     case GraphicsContext3D::COMPRESSED_TEXTURE_FORMATS:
    979         // Defined as null in the spec
    980         return WebGLGetInfo();
    981     case GraphicsContext3D::CULL_FACE:
    982         return getBooleanParameter(pname);
    983     case GraphicsContext3D::CULL_FACE_MODE:
    984         return getUnsignedLongParameter(pname);
    985     case GraphicsContext3D::CURRENT_PROGRAM:
    986         return WebGLGetInfo(PassRefPtr<WebGLProgram>(m_currentProgram));
    987     case GraphicsContext3D::DEPTH_BITS:
    988         return getLongParameter(pname);
    989     case GraphicsContext3D::DEPTH_CLEAR_VALUE:
    990         return getFloatParameter(pname);
    991     case GraphicsContext3D::DEPTH_FUNC:
    992         return getUnsignedLongParameter(pname);
    993     case GraphicsContext3D::DEPTH_RANGE:
    994         return getWebGLFloatArrayParameter(pname);
    995     case GraphicsContext3D::DEPTH_TEST:
    996         return getBooleanParameter(pname);
    997     case GraphicsContext3D::DEPTH_WRITEMASK:
    998         return getBooleanParameter(pname);
    999     case GraphicsContext3D::DITHER:
   1000         return getBooleanParameter(pname);
   1001     case GraphicsContext3D::ELEMENT_ARRAY_BUFFER_BINDING:
   1002         return WebGLGetInfo(PassRefPtr<WebGLBuffer>(m_boundElementArrayBuffer));
   1003     case GraphicsContext3D::FRAMEBUFFER_BINDING:
   1004         return WebGLGetInfo(PassRefPtr<WebGLFramebuffer>(m_framebufferBinding));
   1005     case GraphicsContext3D::FRONT_FACE:
   1006         return getUnsignedLongParameter(pname);
   1007     case GraphicsContext3D::GENERATE_MIPMAP_HINT:
   1008         return getUnsignedLongParameter(pname);
   1009     case GraphicsContext3D::GREEN_BITS:
   1010         return getLongParameter(pname);
   1011     case GraphicsContext3D::LINE_WIDTH:
   1012         return getFloatParameter(pname);
   1013     case GraphicsContext3D::MAX_COMBINED_TEXTURE_IMAGE_UNITS:
   1014         return getLongParameter(pname);
   1015     case GraphicsContext3D::MAX_CUBE_MAP_TEXTURE_SIZE:
   1016         return getLongParameter(pname);
   1017     case GraphicsContext3D::MAX_FRAGMENT_UNIFORM_VECTORS:
   1018         return getLongParameter(pname);
   1019     case GraphicsContext3D::MAX_RENDERBUFFER_SIZE:
   1020         return getLongParameter(pname);
   1021     case GraphicsContext3D::MAX_TEXTURE_IMAGE_UNITS:
   1022         return getLongParameter(pname);
   1023     case GraphicsContext3D::MAX_TEXTURE_SIZE:
   1024         return getLongParameter(pname);
   1025     case GraphicsContext3D::MAX_VARYING_VECTORS:
   1026         return getLongParameter(pname);
   1027     case GraphicsContext3D::MAX_VERTEX_ATTRIBS:
   1028         return getLongParameter(pname);
   1029     case GraphicsContext3D::MAX_VERTEX_TEXTURE_IMAGE_UNITS:
   1030         return getLongParameter(pname);
   1031     case GraphicsContext3D::MAX_VERTEX_UNIFORM_VECTORS:
   1032         return getLongParameter(pname);
   1033     case GraphicsContext3D::MAX_VIEWPORT_DIMS:
   1034         return getWebGLIntArrayParameter(pname);
   1035     case GraphicsContext3D::NUM_COMPRESSED_TEXTURE_FORMATS:
   1036         return getLongParameter(pname);
   1037     case GraphicsContext3D::NUM_SHADER_BINARY_FORMATS:
   1038         // FIXME: should we always return 0 for this?
   1039         return getLongParameter(pname);
   1040     case GraphicsContext3D::PACK_ALIGNMENT:
   1041         return getLongParameter(pname);
   1042     case GraphicsContext3D::POLYGON_OFFSET_FACTOR:
   1043         return getFloatParameter(pname);
   1044     case GraphicsContext3D::POLYGON_OFFSET_FILL:
   1045         return getBooleanParameter(pname);
   1046     case GraphicsContext3D::POLYGON_OFFSET_UNITS:
   1047         return getFloatParameter(pname);
   1048     case GraphicsContext3D::RED_BITS:
   1049         return getLongParameter(pname);
   1050     case GraphicsContext3D::RENDERBUFFER_BINDING:
   1051         return WebGLGetInfo(PassRefPtr<WebGLRenderbuffer>(m_renderbufferBinding));
   1052     case GraphicsContext3D::SAMPLE_BUFFERS:
   1053         return getLongParameter(pname);
   1054     case GraphicsContext3D::SAMPLE_COVERAGE_INVERT:
   1055         return getBooleanParameter(pname);
   1056     case GraphicsContext3D::SAMPLE_COVERAGE_VALUE:
   1057         return getFloatParameter(pname);
   1058     case GraphicsContext3D::SAMPLES:
   1059         return getLongParameter(pname);
   1060     case GraphicsContext3D::SCISSOR_BOX:
   1061         return getWebGLIntArrayParameter(pname);
   1062     case GraphicsContext3D::SCISSOR_TEST:
   1063         return getBooleanParameter(pname);
   1064     case GraphicsContext3D::STENCIL_BACK_FAIL:
   1065         return getUnsignedLongParameter(pname);
   1066     case GraphicsContext3D::STENCIL_BACK_FUNC:
   1067         return getUnsignedLongParameter(pname);
   1068     case GraphicsContext3D::STENCIL_BACK_PASS_DEPTH_FAIL:
   1069         return getUnsignedLongParameter(pname);
   1070     case GraphicsContext3D::STENCIL_BACK_PASS_DEPTH_PASS:
   1071         return getUnsignedLongParameter(pname);
   1072     case GraphicsContext3D::STENCIL_BACK_REF:
   1073         return getLongParameter(pname);
   1074     case GraphicsContext3D::STENCIL_BACK_VALUE_MASK:
   1075         return getUnsignedLongParameter(pname);
   1076     case GraphicsContext3D::STENCIL_BACK_WRITEMASK:
   1077         return getUnsignedLongParameter(pname);
   1078     case GraphicsContext3D::STENCIL_BITS:
   1079         return getLongParameter(pname);
   1080     case GraphicsContext3D::STENCIL_CLEAR_VALUE:
   1081         return getLongParameter(pname);
   1082     case GraphicsContext3D::STENCIL_FAIL:
   1083         return getUnsignedLongParameter(pname);
   1084     case GraphicsContext3D::STENCIL_FUNC:
   1085         return getUnsignedLongParameter(pname);
   1086     case GraphicsContext3D::STENCIL_PASS_DEPTH_FAIL:
   1087         return getUnsignedLongParameter(pname);
   1088     case GraphicsContext3D::STENCIL_PASS_DEPTH_PASS:
   1089         return getUnsignedLongParameter(pname);
   1090     case GraphicsContext3D::STENCIL_REF:
   1091         return getLongParameter(pname);
   1092     case GraphicsContext3D::STENCIL_TEST:
   1093         return getBooleanParameter(pname);
   1094     case GraphicsContext3D::STENCIL_VALUE_MASK:
   1095         return getUnsignedLongParameter(pname);
   1096     case GraphicsContext3D::STENCIL_WRITEMASK:
   1097         return getUnsignedLongParameter(pname);
   1098     case GraphicsContext3D::SUBPIXEL_BITS:
   1099         return getLongParameter(pname);
   1100     case GraphicsContext3D::TEXTURE_BINDING_2D:
   1101         return WebGLGetInfo(PassRefPtr<WebGLTexture>(m_textureUnits[m_activeTextureUnit].m_texture2DBinding));
   1102     case GraphicsContext3D::TEXTURE_BINDING_CUBE_MAP:
   1103         return WebGLGetInfo(PassRefPtr<WebGLTexture>(m_textureUnits[m_activeTextureUnit].m_textureCubeMapBinding));
   1104     case GraphicsContext3D::UNPACK_ALIGNMENT:
   1105         // FIXME: should this be "long" in the spec?
   1106         return getIntParameter(pname);
   1107     case GraphicsContext3D::VIEWPORT:
   1108         return getWebGLIntArrayParameter(pname);
   1109     default:
   1110         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
   1111         return WebGLGetInfo();
   1112     }
   1113 }
   1114 
   1115 WebGLGetInfo WebGLRenderingContext::getProgramParameter(WebGLProgram* program, unsigned long pname, ExceptionCode& ec)
   1116 {
   1117     UNUSED_PARAM(ec);
   1118     if (!program || program->context() != this) {
   1119         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
   1120         return WebGLGetInfo();
   1121     }
   1122 
   1123     WebGLStateRestorer(this, false);
   1124     int value = 0;
   1125     switch (pname) {
   1126     case GraphicsContext3D::DELETE_STATUS:
   1127     case GraphicsContext3D::LINK_STATUS:
   1128     case GraphicsContext3D::VALIDATE_STATUS:
   1129         m_context->getProgramiv(program, pname, &value);
   1130         return WebGLGetInfo(static_cast<bool>(value));
   1131     case GraphicsContext3D::INFO_LOG_LENGTH:
   1132     case GraphicsContext3D::ATTACHED_SHADERS:
   1133     case GraphicsContext3D::ACTIVE_ATTRIBUTES:
   1134     case GraphicsContext3D::ACTIVE_ATTRIBUTE_MAX_LENGTH:
   1135     case GraphicsContext3D::ACTIVE_UNIFORMS:
   1136     case GraphicsContext3D::ACTIVE_UNIFORM_MAX_LENGTH:
   1137         m_context->getProgramiv(program, pname, &value);
   1138         return WebGLGetInfo(static_cast<long>(value));
   1139     default:
   1140         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
   1141         return WebGLGetInfo();
   1142     }
   1143 }
   1144 
   1145 String WebGLRenderingContext::getProgramInfoLog(WebGLProgram* program, ExceptionCode& ec)
   1146 {
   1147     UNUSED_PARAM(ec);
   1148     if (!program || program->context() != this) {
   1149         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
   1150         return "";
   1151     }
   1152     WebGLStateRestorer(this, false);
   1153     return m_context->getProgramInfoLog(program);
   1154 }
   1155 
   1156 WebGLGetInfo WebGLRenderingContext::getRenderbufferParameter(unsigned long target, unsigned long pname, ExceptionCode& ec)
   1157 {
   1158     UNUSED_PARAM(ec);
   1159     if (target != GraphicsContext3D::RENDERBUFFER) {
   1160         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
   1161         return WebGLGetInfo();
   1162     }
   1163 
   1164     WebGLStateRestorer(this, false);
   1165     int value = 0;
   1166     switch (pname) {
   1167     case GraphicsContext3D::RENDERBUFFER_WIDTH:
   1168     case GraphicsContext3D::RENDERBUFFER_HEIGHT:
   1169     case GraphicsContext3D::RENDERBUFFER_RED_SIZE:
   1170     case GraphicsContext3D::RENDERBUFFER_GREEN_SIZE:
   1171     case GraphicsContext3D::RENDERBUFFER_BLUE_SIZE:
   1172     case GraphicsContext3D::RENDERBUFFER_ALPHA_SIZE:
   1173     case GraphicsContext3D::RENDERBUFFER_DEPTH_SIZE:
   1174     case GraphicsContext3D::RENDERBUFFER_STENCIL_SIZE:
   1175         m_context->getRenderbufferParameteriv(target, pname, &value);
   1176         return WebGLGetInfo(static_cast<long>(value));
   1177     case GraphicsContext3D::RENDERBUFFER_INTERNAL_FORMAT:
   1178         m_context->getRenderbufferParameteriv(target, pname, &value);
   1179         return WebGLGetInfo(static_cast<unsigned long>(value));
   1180     default:
   1181         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
   1182         return WebGLGetInfo();
   1183     }
   1184 }
   1185 
   1186 WebGLGetInfo WebGLRenderingContext::getShaderParameter(WebGLShader* shader, unsigned long pname, ExceptionCode& ec)
   1187 {
   1188     UNUSED_PARAM(ec);
   1189     if (!shader || shader->context() != this) {
   1190         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
   1191         return WebGLGetInfo();
   1192     }
   1193     WebGLStateRestorer(this, false);
   1194     int value = 0;
   1195     switch (pname) {
   1196     case GraphicsContext3D::DELETE_STATUS:
   1197     case GraphicsContext3D::COMPILE_STATUS:
   1198         m_context->getShaderiv(shader, pname, &value);
   1199         return WebGLGetInfo(static_cast<bool>(value));
   1200     case GraphicsContext3D::SHADER_TYPE:
   1201         m_context->getShaderiv(shader, pname, &value);
   1202         return WebGLGetInfo(static_cast<unsigned long>(value));
   1203     case GraphicsContext3D::INFO_LOG_LENGTH:
   1204     case GraphicsContext3D::SHADER_SOURCE_LENGTH:
   1205         m_context->getShaderiv(shader, pname, &value);
   1206         return WebGLGetInfo(static_cast<long>(value));
   1207     default:
   1208         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
   1209         return WebGLGetInfo();
   1210     }
   1211 }
   1212 
   1213 String WebGLRenderingContext::getShaderInfoLog(WebGLShader* shader, ExceptionCode& ec)
   1214 {
   1215     UNUSED_PARAM(ec);
   1216     if (!shader || shader->context() != this) {
   1217         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
   1218         return "";
   1219     }
   1220     WebGLStateRestorer(this, false);
   1221     return m_context->getShaderInfoLog(shader);
   1222 }
   1223 
   1224 String WebGLRenderingContext::getShaderSource(WebGLShader* shader, ExceptionCode& ec)
   1225 {
   1226     UNUSED_PARAM(ec);
   1227     if (!shader || shader->context() != this) {
   1228         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
   1229         return "";
   1230     }
   1231     WebGLStateRestorer(this, false);
   1232     return m_context->getShaderSource(shader);
   1233 }
   1234 
   1235 String WebGLRenderingContext::getString(unsigned long name)
   1236 {
   1237     WebGLStateRestorer(this, false);
   1238     return m_context->getString(name);
   1239 }
   1240 
   1241 WebGLGetInfo WebGLRenderingContext::getTexParameter(unsigned long target, unsigned long pname, ExceptionCode& ec)
   1242 {
   1243     UNUSED_PARAM(ec);
   1244     if (target != GraphicsContext3D::TEXTURE_2D
   1245         && target != GraphicsContext3D::TEXTURE_CUBE_MAP) {
   1246         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
   1247         return WebGLGetInfo();
   1248     }
   1249     WebGLStateRestorer(this, false);
   1250     int value = 0;
   1251     switch (pname) {
   1252     case GraphicsContext3D::TEXTURE_MAG_FILTER:
   1253     case GraphicsContext3D::TEXTURE_MIN_FILTER:
   1254     case GraphicsContext3D::TEXTURE_WRAP_S:
   1255     case GraphicsContext3D::TEXTURE_WRAP_T:
   1256         m_context->getTexParameteriv(target, pname, &value);
   1257         return WebGLGetInfo(static_cast<unsigned long>(value));
   1258     default:
   1259         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
   1260         return WebGLGetInfo();
   1261     }
   1262 }
   1263 
   1264 WebGLGetInfo WebGLRenderingContext::getUniform(WebGLProgram* program, const WebGLUniformLocation* uniformLocation, ExceptionCode& ec)
   1265 {
   1266     UNUSED_PARAM(ec);
   1267     if (!program || uniformLocation->program() != program || program->context() != this) {
   1268         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
   1269         return WebGLGetInfo();
   1270     }
   1271     long location = uniformLocation->location();
   1272 
   1273     WebGLStateRestorer(this, false);
   1274     // FIXME: make this more efficient using WebGLUniformLocation and caching types in it
   1275     int activeUniforms = 0;
   1276     m_context->getProgramiv(program, GraphicsContext3D::ACTIVE_UNIFORMS, &activeUniforms);
   1277     for (int i = 0; i < activeUniforms; i++) {
   1278         ActiveInfo info;
   1279         if (!m_context->getActiveUniform(program, i, info))
   1280             return WebGLGetInfo();
   1281         // Now need to look this up by name again to find its location
   1282         long loc = m_context->getUniformLocation(program, info.name);
   1283         if (loc == location) {
   1284             // Found it. Use the type in the ActiveInfo to determine the return type.
   1285             GraphicsContext3D::WebGLEnumType baseType;
   1286             unsigned length;
   1287             switch (info.type) {
   1288                 case GraphicsContext3D::BOOL:
   1289                     baseType = GraphicsContext3D::BOOL;
   1290                     length = 1;
   1291                     break;
   1292                 case GraphicsContext3D::BOOL_VEC2:
   1293                     baseType = GraphicsContext3D::BOOL;
   1294                     length = 2;
   1295                     break;
   1296                 case GraphicsContext3D::BOOL_VEC3:
   1297                     baseType = GraphicsContext3D::BOOL;
   1298                     length = 3;
   1299                     break;
   1300                 case GraphicsContext3D::BOOL_VEC4:
   1301                     baseType = GraphicsContext3D::BOOL;
   1302                     length = 4;
   1303                     break;
   1304                 case GraphicsContext3D::INT:
   1305                     baseType = GraphicsContext3D::INT;
   1306                     length = 1;
   1307                     break;
   1308                 case GraphicsContext3D::INT_VEC2:
   1309                     baseType = GraphicsContext3D::INT;
   1310                     length = 2;
   1311                     break;
   1312                 case GraphicsContext3D::INT_VEC3:
   1313                     baseType = GraphicsContext3D::INT;
   1314                     length = 3;
   1315                     break;
   1316                 case GraphicsContext3D::INT_VEC4:
   1317                     baseType = GraphicsContext3D::INT;
   1318                     length = 4;
   1319                     break;
   1320                 case GraphicsContext3D::FLOAT:
   1321                     baseType = GraphicsContext3D::FLOAT;
   1322                     length = 1;
   1323                     break;
   1324                 case GraphicsContext3D::FLOAT_VEC2:
   1325                     baseType = GraphicsContext3D::FLOAT;
   1326                     length = 2;
   1327                     break;
   1328                 case GraphicsContext3D::FLOAT_VEC3:
   1329                     baseType = GraphicsContext3D::FLOAT;
   1330                     length = 3;
   1331                     break;
   1332                 case GraphicsContext3D::FLOAT_VEC4:
   1333                     baseType = GraphicsContext3D::FLOAT;
   1334                     length = 4;
   1335                     break;
   1336                 case GraphicsContext3D::FLOAT_MAT2:
   1337                     baseType = GraphicsContext3D::FLOAT;
   1338                     length = 4;
   1339                     break;
   1340                 case GraphicsContext3D::FLOAT_MAT3:
   1341                     baseType = GraphicsContext3D::FLOAT;
   1342                     length = 9;
   1343                     break;
   1344                 case GraphicsContext3D::FLOAT_MAT4:
   1345                     baseType = GraphicsContext3D::FLOAT;
   1346                     length = 16;
   1347                     break;
   1348                 default:
   1349                     // Can't handle this type
   1350                     // FIXME: what to do about samplers?
   1351                     m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
   1352                     return WebGLGetInfo();
   1353             }
   1354             switch (baseType) {
   1355             case GraphicsContext3D::FLOAT: {
   1356                 float value[16] = {0};
   1357                 m_context->getUniformfv(program, location, value);
   1358                 if (length == 1)
   1359                     return WebGLGetInfo(value[0]);
   1360                 else
   1361                     return WebGLGetInfo(WebGLFloatArray::create(value, length));
   1362             }
   1363             case GraphicsContext3D::INT: {
   1364                 int value[16] = {0};
   1365                 m_context->getUniformiv(program, location, value);
   1366                 if (length == 1)
   1367                     return WebGLGetInfo(static_cast<long>(value[0]));
   1368                 else
   1369                     return WebGLGetInfo(WebGLIntArray::create(value, length));
   1370             }
   1371             case GraphicsContext3D::BOOL: {
   1372                 int value[16] = {0};
   1373                 m_context->getUniformiv(program, location, value);
   1374                 if (length == 1)
   1375                     return WebGLGetInfo(static_cast<bool>(value[0]));
   1376                 else {
   1377                     unsigned char boolValue[16] = {0};
   1378                     for (unsigned j = 0; j < length; j++)
   1379                         boolValue[j] = static_cast<bool>(value[j]);
   1380                     return WebGLGetInfo(WebGLUnsignedByteArray::create(boolValue, length));
   1381                 }
   1382             }
   1383             default:
   1384                 notImplemented();
   1385             }
   1386         }
   1387     }
   1388     // If we get here, something went wrong in our unfortunately complex logic above
   1389     m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
   1390     return WebGLGetInfo();
   1391 }
   1392 
   1393 PassRefPtr<WebGLUniformLocation> WebGLRenderingContext::getUniformLocation(WebGLProgram* program, const String& name, ExceptionCode& ec)
   1394 {
   1395     UNUSED_PARAM(ec);
   1396     if (!program || program->context() != this) {
   1397         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
   1398         return 0;
   1399     }
   1400     WebGLStateRestorer(this, false);
   1401     return WebGLUniformLocation::create(program, m_context->getUniformLocation(program, name));
   1402 }
   1403 
   1404 WebGLGetInfo WebGLRenderingContext::getVertexAttrib(unsigned long index, unsigned long pname, ExceptionCode& ec)
   1405 {
   1406     UNUSED_PARAM(ec);
   1407     WebGLStateRestorer(this, false);
   1408     switch (pname) {
   1409     case GraphicsContext3D::VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: {
   1410         int name = 0;
   1411         m_context->getVertexAttribiv(index, pname, &name);
   1412         if (name == 0)
   1413             return WebGLGetInfo();
   1414         RefPtr<WebGLBuffer> tmp = WebGLBuffer::create(this, name);
   1415         addObject(tmp.get());
   1416         return WebGLGetInfo(PassRefPtr<WebGLBuffer>(tmp));
   1417     }
   1418     case GraphicsContext3D::VERTEX_ATTRIB_ARRAY_ENABLED:
   1419     case GraphicsContext3D::VERTEX_ATTRIB_ARRAY_NORMALIZED: {
   1420         int value = 0;
   1421         m_context->getVertexAttribiv(index, pname, &value);
   1422         return WebGLGetInfo(static_cast<bool>(value));
   1423     }
   1424     case GraphicsContext3D::VERTEX_ATTRIB_ARRAY_SIZE:
   1425     case GraphicsContext3D::VERTEX_ATTRIB_ARRAY_STRIDE: {
   1426         int value = 0;
   1427         m_context->getVertexAttribiv(index, pname, &value);
   1428         return WebGLGetInfo(static_cast<long>(value));
   1429     }
   1430     case GraphicsContext3D::VERTEX_ATTRIB_ARRAY_TYPE: {
   1431         int value = 0;
   1432         m_context->getVertexAttribiv(index, pname, &value);
   1433         return WebGLGetInfo(static_cast<unsigned long>(value));
   1434     }
   1435     case GraphicsContext3D::CURRENT_VERTEX_ATTRIB: {
   1436         float value[4] = {0};
   1437         m_context->getVertexAttribfv(index, pname, value);
   1438         return WebGLGetInfo(WebGLFloatArray::create(value, 4));
   1439     }
   1440     default: {
   1441         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
   1442         return WebGLGetInfo();
   1443     }
   1444     }
   1445 }
   1446 
   1447 long WebGLRenderingContext::getVertexAttribOffset(unsigned long index, unsigned long pname)
   1448 {
   1449     long result = m_context->getVertexAttribOffset(index, pname);
   1450     cleanupAfterGraphicsCall(false);
   1451     return result;
   1452 }
   1453 
   1454 void WebGLRenderingContext::hint(unsigned long target, unsigned long mode)
   1455 {
   1456     m_context->hint(target, mode);
   1457     cleanupAfterGraphicsCall(false);
   1458 }
   1459 
   1460 bool WebGLRenderingContext::isBuffer(WebGLBuffer* buffer)
   1461 {
   1462     if (!buffer)
   1463         return false;
   1464 
   1465     return m_context->isBuffer(buffer);
   1466 }
   1467 
   1468 bool WebGLRenderingContext::isEnabled(unsigned long cap)
   1469 {
   1470     return m_context->isEnabled(cap);
   1471 }
   1472 
   1473 bool WebGLRenderingContext::isFramebuffer(WebGLFramebuffer* framebuffer)
   1474 {
   1475     if (!framebuffer)
   1476         return false;
   1477 
   1478     return m_context->isFramebuffer(framebuffer);
   1479 }
   1480 
   1481 bool WebGLRenderingContext::isProgram(WebGLProgram* program)
   1482 {
   1483     if (!program)
   1484         return false;
   1485 
   1486     return m_context->isProgram(program);
   1487 }
   1488 
   1489 bool WebGLRenderingContext::isRenderbuffer(WebGLRenderbuffer* renderbuffer)
   1490 {
   1491     if (!renderbuffer)
   1492         return false;
   1493 
   1494     return m_context->isRenderbuffer(renderbuffer);
   1495 }
   1496 
   1497 bool WebGLRenderingContext::isShader(WebGLShader* shader)
   1498 {
   1499     if (!shader)
   1500         return false;
   1501 
   1502     return m_context->isShader(shader);
   1503 }
   1504 
   1505 bool WebGLRenderingContext::isTexture(WebGLTexture* texture)
   1506 {
   1507     if (!texture)
   1508         return false;
   1509 
   1510     return m_context->isTexture(texture);
   1511 }
   1512 
   1513 void WebGLRenderingContext::lineWidth(double width)
   1514 {
   1515     m_context->lineWidth((float) width);
   1516     cleanupAfterGraphicsCall(false);
   1517 }
   1518 
   1519 void WebGLRenderingContext::linkProgram(WebGLProgram* program, ExceptionCode& ec)
   1520 {
   1521     UNUSED_PARAM(ec);
   1522     if (!program || program->context() != this) {
   1523         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
   1524         return;
   1525     }
   1526 
   1527     m_context->linkProgram(program);
   1528     cleanupAfterGraphicsCall(false);
   1529 }
   1530 
   1531 void WebGLRenderingContext::pixelStorei(unsigned long pname, long param)
   1532 {
   1533     m_context->pixelStorei(pname, param);
   1534     cleanupAfterGraphicsCall(false);
   1535 }
   1536 
   1537 void WebGLRenderingContext::polygonOffset(double factor, double units)
   1538 {
   1539     m_context->polygonOffset((float) factor, (float) units);
   1540     cleanupAfterGraphicsCall(false);
   1541 }
   1542 
   1543 PassRefPtr<WebGLArray> WebGLRenderingContext::readPixels(long x, long y, unsigned long width, unsigned long height, unsigned long format, unsigned long type)
   1544 {
   1545     RefPtr<WebGLArray> array = m_context->readPixels(x, y, width, height, format, type);
   1546     cleanupAfterGraphicsCall(false);
   1547     return array;
   1548 }
   1549 
   1550 void WebGLRenderingContext::releaseShaderCompiler()
   1551 {
   1552     m_context->releaseShaderCompiler();
   1553     cleanupAfterGraphicsCall(false);
   1554 }
   1555 
   1556 void WebGLRenderingContext::renderbufferStorage(unsigned long target, unsigned long internalformat, unsigned long width, unsigned long height)
   1557 {
   1558     m_context->renderbufferStorage(target, internalformat, width, height);
   1559     cleanupAfterGraphicsCall(false);
   1560 }
   1561 
   1562 void WebGLRenderingContext::sampleCoverage(double value, bool invert)
   1563 {
   1564     m_context->sampleCoverage((float) value, invert);
   1565     cleanupAfterGraphicsCall(false);
   1566 }
   1567 
   1568 void WebGLRenderingContext::scissor(long x, long y, unsigned long width, unsigned long height)
   1569 {
   1570     m_context->scissor(x, y, width, height);
   1571     cleanupAfterGraphicsCall(false);
   1572 }
   1573 
   1574 void WebGLRenderingContext::shaderSource(WebGLShader* shader, const String& string, ExceptionCode& ec)
   1575 {
   1576     UNUSED_PARAM(ec);
   1577     if (!shader || shader->context() != this) {
   1578         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
   1579         return;
   1580     }
   1581     m_context->shaderSource(shader, string);
   1582     cleanupAfterGraphicsCall(false);
   1583 }
   1584 
   1585 void WebGLRenderingContext::stencilFunc(unsigned long func, long ref, unsigned long mask)
   1586 {
   1587     m_context->stencilFunc(func, ref, mask);
   1588     cleanupAfterGraphicsCall(false);
   1589 }
   1590 
   1591 void WebGLRenderingContext::stencilFuncSeparate(unsigned long face, unsigned long func, long ref, unsigned long mask)
   1592 {
   1593     m_context->stencilFuncSeparate(face, func, ref, mask);
   1594     cleanupAfterGraphicsCall(false);
   1595 }
   1596 
   1597 void WebGLRenderingContext::stencilMask(unsigned long mask)
   1598 {
   1599     m_context->stencilMask(mask);
   1600     cleanupAfterGraphicsCall(false);
   1601 }
   1602 
   1603 void WebGLRenderingContext::stencilMaskSeparate(unsigned long face, unsigned long mask)
   1604 {
   1605     m_context->stencilMaskSeparate(face, mask);
   1606     cleanupAfterGraphicsCall(false);
   1607 }
   1608 
   1609 void WebGLRenderingContext::stencilOp(unsigned long fail, unsigned long zfail, unsigned long zpass)
   1610 {
   1611     m_context->stencilOp(fail, zfail, zpass);
   1612     cleanupAfterGraphicsCall(false);
   1613 }
   1614 
   1615 void WebGLRenderingContext::stencilOpSeparate(unsigned long face, unsigned long fail, unsigned long zfail, unsigned long zpass)
   1616 {
   1617     m_context->stencilOpSeparate(face, fail, zfail, zpass);
   1618     cleanupAfterGraphicsCall(false);
   1619 }
   1620 
   1621 void WebGLRenderingContext::texImage2D(unsigned target, unsigned level, unsigned internalformat,
   1622                                           unsigned width, unsigned height, unsigned border,
   1623                                           unsigned format, unsigned type, WebGLArray* pixels, ExceptionCode& ec)
   1624 {
   1625     // FIXME: For now we ignore any errors returned
   1626     // FIXME: Need to make sure passed buffer has enough bytes to define the texture
   1627     ec = 0;
   1628     m_context->texImage2D(target, level, internalformat, width, height,
   1629                           border, format, type, pixels ? pixels->baseAddress() : 0);
   1630     cleanupAfterGraphicsCall(false);
   1631 }
   1632 
   1633 void WebGLRenderingContext::texImage2D(unsigned target, unsigned level, ImageData* pixels,
   1634                                        bool flipY, bool premultiplyAlpha, ExceptionCode& ec)
   1635 {
   1636     // FIXME: For now we ignore any errors returned
   1637     // FIXME: Need a form of this call that can take both a pixel buffer and flipY and premultiplyAlpha flags
   1638     UNUSED_PARAM(flipY);
   1639     UNUSED_PARAM(premultiplyAlpha);
   1640     ec = 0;
   1641     m_context->texImage2D(target, level, GraphicsContext3D::RGBA, pixels->width(), pixels->height(), 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, pixels->data()->data()->data());
   1642     //RLP: m_context->texImage2D(target, level, pixels, flipY, premultiplyAlpha);
   1643     cleanupAfterGraphicsCall(false);
   1644 }
   1645 
   1646 void WebGLRenderingContext::texImage2D(unsigned target, unsigned level, HTMLImageElement* image,
   1647                                        bool flipY, bool premultiplyAlpha, ExceptionCode& ec)
   1648 {
   1649     ec = 0;
   1650     if (!image) {
   1651         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
   1652         return;
   1653     }
   1654 
   1655     CachedImage* cachedImage = image->cachedImage();
   1656     if (!cachedImage) {
   1657         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
   1658         return;
   1659     }
   1660 
   1661     // FIXME: For now we ignore any errors returned
   1662     m_context->texImage2D(target, level, cachedImage->image(), flipY, premultiplyAlpha);
   1663     cleanupAfterGraphicsCall(false);
   1664 }
   1665 
   1666 void WebGLRenderingContext::texImage2D(unsigned target, unsigned level, HTMLCanvasElement* canvas,
   1667                                           bool flipY, bool premultiplyAlpha, ExceptionCode& ec)
   1668 {
   1669     ec = 0;
   1670     if (!canvas) {
   1671         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
   1672         return;
   1673     }
   1674 
   1675     ImageBuffer* buffer = canvas->buffer();
   1676     if (!buffer) {
   1677         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
   1678         return;
   1679     }
   1680 
   1681     // FIXME: For now we ignore any errors returned
   1682     m_context->texImage2D(target, level, buffer->image(), flipY, premultiplyAlpha);
   1683     cleanupAfterGraphicsCall(false);
   1684 }
   1685 
   1686 void WebGLRenderingContext::texImage2D(unsigned target, unsigned level, HTMLVideoElement* video,
   1687                                           bool flipY, bool premultiplyAlpha, ExceptionCode& ec)
   1688 {
   1689     // FIXME: Need implement this call
   1690     UNUSED_PARAM(target);
   1691     UNUSED_PARAM(level);
   1692     UNUSED_PARAM(video);
   1693     UNUSED_PARAM(flipY);
   1694     UNUSED_PARAM(premultiplyAlpha);
   1695 
   1696     ec = 0;
   1697     cleanupAfterGraphicsCall(false);
   1698 }
   1699 
   1700 void WebGLRenderingContext::texParameterf(unsigned target, unsigned pname, float param)
   1701 {
   1702     m_context->texParameterf(target, pname, param);
   1703     cleanupAfterGraphicsCall(false);
   1704 }
   1705 
   1706 void WebGLRenderingContext::texParameteri(unsigned target, unsigned pname, int param)
   1707 {
   1708     m_context->texParameteri(target, pname, param);
   1709     cleanupAfterGraphicsCall(false);
   1710 }
   1711 
   1712 void WebGLRenderingContext::texSubImage2D(unsigned target, unsigned level, unsigned xoffset, unsigned yoffset,
   1713                                              unsigned width, unsigned height,
   1714                                              unsigned format, unsigned type, WebGLArray* pixels, ExceptionCode& ec)
   1715 {
   1716     // FIXME: For now we ignore any errors returned
   1717     // FIXME: Need to make sure passed buffer has enough bytes to define the texture
   1718     ec = 0;
   1719     m_context->texSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels ? pixels->baseAddress() : 0);
   1720     cleanupAfterGraphicsCall(false);
   1721 }
   1722 
   1723 void WebGLRenderingContext::texSubImage2D(unsigned target, unsigned level, unsigned xoffset, unsigned yoffset,
   1724                                           ImageData* pixels, bool flipY, bool premultiplyAlpha, ExceptionCode& ec)
   1725 {
   1726     // FIXME: For now we ignore any errors returned
   1727     UNUSED_PARAM(flipY);
   1728     UNUSED_PARAM(premultiplyAlpha);
   1729     ec = 0;
   1730     m_context->texSubImage2D(target, level, xoffset, yoffset, pixels->width(), pixels->height(), GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, pixels->data()->data()->data());
   1731     //RLP: m_context->texSubImage2D(target, level, xoffset, yoffset, pixels, flipY, premultiplyAlpha);
   1732     cleanupAfterGraphicsCall(false);
   1733 }
   1734 
   1735 void WebGLRenderingContext::texSubImage2D(unsigned target, unsigned level, unsigned xoffset, unsigned yoffset,
   1736                                           HTMLImageElement* image, bool flipY, bool premultiplyAlpha, ExceptionCode& ec)
   1737 {
   1738     // FIXME: For now we ignore any errors returned
   1739     ec = 0;
   1740     if (!image) {
   1741         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
   1742         return;
   1743     }
   1744 
   1745     CachedImage* cachedImage = image->cachedImage();
   1746     if (!cachedImage) {
   1747         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
   1748         return;
   1749     }
   1750 
   1751     m_context->texSubImage2D(target, level, xoffset, yoffset, cachedImage->image(), flipY, premultiplyAlpha);
   1752     cleanupAfterGraphicsCall(false);
   1753 }
   1754 
   1755 void WebGLRenderingContext::texSubImage2D(unsigned target, unsigned level, unsigned xoffset, unsigned yoffset,
   1756                                           HTMLCanvasElement* canvas, bool flipY, bool premultiplyAlpha, ExceptionCode& ec)
   1757 {
   1758     ec = 0;
   1759     if (!canvas) {
   1760         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
   1761         return;
   1762     }
   1763 
   1764     ImageBuffer* buffer = canvas->buffer();
   1765     if (!buffer) {
   1766         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
   1767         return;
   1768     }
   1769 
   1770     // FIXME: For now we ignore any errors returned
   1771     m_context->texSubImage2D(target, level, xoffset, yoffset, buffer->image(), flipY, premultiplyAlpha);
   1772     cleanupAfterGraphicsCall(false);
   1773 }
   1774 
   1775 void WebGLRenderingContext::texSubImage2D(unsigned target, unsigned level, unsigned xoffset, unsigned yoffset,
   1776                                           HTMLVideoElement* video, bool flipY, bool premultiplyAlpha, ExceptionCode& ec)
   1777 {
   1778     // FIXME: Need to implement this call
   1779     UNUSED_PARAM(target);
   1780     UNUSED_PARAM(level);
   1781     UNUSED_PARAM(xoffset);
   1782     UNUSED_PARAM(yoffset);
   1783     UNUSED_PARAM(video);
   1784     UNUSED_PARAM(flipY);
   1785     UNUSED_PARAM(premultiplyAlpha);
   1786     ec = 0;
   1787     cleanupAfterGraphicsCall(false);
   1788 }
   1789 
   1790 void WebGLRenderingContext::uniform1f(const WebGLUniformLocation* location, float x, ExceptionCode& ec)
   1791 {
   1792     UNUSED_PARAM(ec);
   1793     if (!location || location->program() != m_currentProgram) {
   1794         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
   1795         return;
   1796     }
   1797 
   1798     m_context->uniform1f(location->location(), x);
   1799     cleanupAfterGraphicsCall(false);
   1800 }
   1801 
   1802 void WebGLRenderingContext::uniform1fv(const WebGLUniformLocation* location, WebGLFloatArray* v, ExceptionCode& ec)
   1803 {
   1804     UNUSED_PARAM(ec);
   1805     if (!location || location->program() != m_currentProgram) {
   1806         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
   1807         return;
   1808     }
   1809 
   1810     if (!v) {
   1811         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
   1812         return;
   1813     }
   1814     m_context->uniform1fv(location->location(), v->data(), v->length());
   1815     cleanupAfterGraphicsCall(false);
   1816 }
   1817 
   1818 void WebGLRenderingContext::uniform1fv(const WebGLUniformLocation* location, float* v, int size, ExceptionCode& ec)
   1819 {
   1820     UNUSED_PARAM(ec);
   1821     if (!location || location->program() != m_currentProgram) {
   1822         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
   1823         return;
   1824     }
   1825 
   1826     if (!v) {
   1827         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
   1828         return;
   1829     }
   1830     m_context->uniform1fv(location->location(), v, size);
   1831     cleanupAfterGraphicsCall(false);
   1832 }
   1833 
   1834 void WebGLRenderingContext::uniform1i(const WebGLUniformLocation* location, int x, ExceptionCode& ec)
   1835 {
   1836     UNUSED_PARAM(ec);
   1837     if (!location || location->program() != m_currentProgram) {
   1838         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
   1839         return;
   1840     }
   1841 
   1842     m_context->uniform1i(location->location(), x);
   1843     cleanupAfterGraphicsCall(false);
   1844 }
   1845 
   1846 void WebGLRenderingContext::uniform1iv(const WebGLUniformLocation* location, WebGLIntArray* v, ExceptionCode& ec)
   1847 {
   1848     UNUSED_PARAM(ec);
   1849     if (!location || location->program() != m_currentProgram) {
   1850         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
   1851         return;
   1852     }
   1853 
   1854     if (!v) {
   1855         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
   1856         return;
   1857     }
   1858     m_context->uniform1iv(location->location(), v->data(), v->length());
   1859     cleanupAfterGraphicsCall(false);
   1860 }
   1861 
   1862 void WebGLRenderingContext::uniform1iv(const WebGLUniformLocation* location, int* v, int size, ExceptionCode& ec)
   1863 {
   1864     UNUSED_PARAM(ec);
   1865     if (!location || location->program() != m_currentProgram) {
   1866         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
   1867         return;
   1868     }
   1869 
   1870     if (!v) {
   1871         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
   1872         return;
   1873     }
   1874     m_context->uniform1iv(location->location(), v, size);
   1875     cleanupAfterGraphicsCall(false);
   1876 }
   1877 
   1878 void WebGLRenderingContext::uniform2f(const WebGLUniformLocation* location, float x, float y, ExceptionCode& ec)
   1879 {
   1880     UNUSED_PARAM(ec);
   1881     if (!location || location->program() != m_currentProgram) {
   1882         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
   1883         return;
   1884     }
   1885 
   1886     m_context->uniform2f(location->location(), x, y);
   1887     cleanupAfterGraphicsCall(false);
   1888 }
   1889 
   1890 void WebGLRenderingContext::uniform2fv(const WebGLUniformLocation* location, WebGLFloatArray* v, ExceptionCode& ec)
   1891 {
   1892     UNUSED_PARAM(ec);
   1893     if (!location || location->program() != m_currentProgram) {
   1894         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
   1895         return;
   1896     }
   1897 
   1898     if (!v) {
   1899         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
   1900         return;
   1901     }
   1902     // FIXME: length needs to be a multiple of 2
   1903     m_context->uniform2fv(location->location(), v->data(), v->length() / 2);
   1904     cleanupAfterGraphicsCall(false);
   1905 }
   1906 
   1907 void WebGLRenderingContext::uniform2fv(const WebGLUniformLocation* location, float* v, int size, ExceptionCode& ec)
   1908 {
   1909     UNUSED_PARAM(ec);
   1910     if (!location || location->program() != m_currentProgram) {
   1911         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
   1912         return;
   1913     }
   1914 
   1915     if (!v) {
   1916         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
   1917         return;
   1918     }
   1919     // FIXME: length needs to be a multiple of 2
   1920     m_context->uniform2fv(location->location(), v, size / 2);
   1921     cleanupAfterGraphicsCall(false);
   1922 }
   1923 
   1924 void WebGLRenderingContext::uniform2i(const WebGLUniformLocation* location, int x, int y, ExceptionCode& ec)
   1925 {
   1926     UNUSED_PARAM(ec);
   1927     if (!location || location->program() != m_currentProgram) {
   1928         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
   1929         return;
   1930     }
   1931 
   1932     m_context->uniform2i(location->location(), x, y);
   1933     cleanupAfterGraphicsCall(false);
   1934 }
   1935 
   1936 void WebGLRenderingContext::uniform2iv(const WebGLUniformLocation* location, WebGLIntArray* v, ExceptionCode& ec)
   1937 {
   1938     UNUSED_PARAM(ec);
   1939     if (!location || location->program() != m_currentProgram) {
   1940         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
   1941         return;
   1942     }
   1943 
   1944     if (!v) {
   1945         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
   1946         return;
   1947     }
   1948     // FIXME: length needs to be a multiple of 2
   1949     m_context->uniform2iv(location->location(), v->data(), v->length() / 2);
   1950     cleanupAfterGraphicsCall(false);
   1951 }
   1952 
   1953 void WebGLRenderingContext::uniform2iv(const WebGLUniformLocation* location, int* v, int size, ExceptionCode& ec)
   1954 {
   1955     UNUSED_PARAM(ec);
   1956     if (!location || location->program() != m_currentProgram) {
   1957         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
   1958         return;
   1959     }
   1960 
   1961     if (!v) {
   1962         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
   1963         return;
   1964     }
   1965     // FIXME: length needs to be a multiple of 2
   1966     m_context->uniform2iv(location->location(), v, size / 2);
   1967     cleanupAfterGraphicsCall(false);
   1968 }
   1969 
   1970 void WebGLRenderingContext::uniform3f(const WebGLUniformLocation* location, float x, float y, float z, ExceptionCode& ec)
   1971 {
   1972     UNUSED_PARAM(ec);
   1973     if (!location || location->program() != m_currentProgram) {
   1974         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
   1975         return;
   1976     }
   1977 
   1978     m_context->uniform3f(location->location(), x, y, z);
   1979     cleanupAfterGraphicsCall(false);
   1980 }
   1981 
   1982 void WebGLRenderingContext::uniform3fv(const WebGLUniformLocation* location, WebGLFloatArray* v, ExceptionCode& ec)
   1983 {
   1984     UNUSED_PARAM(ec);
   1985     if (!location || location->program() != m_currentProgram) {
   1986         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
   1987         return;
   1988     }
   1989 
   1990     if (!v) {
   1991         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
   1992         return;
   1993     }
   1994     // FIXME: length needs to be a multiple of 3
   1995     m_context->uniform3fv(location->location(), v->data(), v->length() / 3);
   1996     cleanupAfterGraphicsCall(false);
   1997 }
   1998 
   1999 void WebGLRenderingContext::uniform3fv(const WebGLUniformLocation* location, float* v, int size, ExceptionCode& ec)
   2000 {
   2001     UNUSED_PARAM(ec);
   2002     if (!location || location->program() != m_currentProgram) {
   2003         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
   2004         return;
   2005     }
   2006 
   2007     if (!v) {
   2008         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
   2009         return;
   2010     }
   2011     // FIXME: length needs to be a multiple of 3
   2012     m_context->uniform3fv(location->location(), v, size / 3);
   2013     cleanupAfterGraphicsCall(false);
   2014 }
   2015 
   2016 void WebGLRenderingContext::uniform3i(const WebGLUniformLocation* location, int x, int y, int z, ExceptionCode& ec)
   2017 {
   2018     UNUSED_PARAM(ec);
   2019     if (!location || location->program() != m_currentProgram) {
   2020         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
   2021         return;
   2022     }
   2023 
   2024     m_context->uniform3i(location->location(), x, y, z);
   2025     cleanupAfterGraphicsCall(false);
   2026 }
   2027 
   2028 void WebGLRenderingContext::uniform3iv(const WebGLUniformLocation* location, WebGLIntArray* v, ExceptionCode& ec)
   2029 {
   2030     UNUSED_PARAM(ec);
   2031     if (!location || location->program() != m_currentProgram) {
   2032         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
   2033         return;
   2034     }
   2035 
   2036     if (!v) {
   2037         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
   2038         return;
   2039     }
   2040     // FIXME: length needs to be a multiple of 3
   2041     m_context->uniform3iv(location->location(), v->data(), v->length() / 3);
   2042     cleanupAfterGraphicsCall(false);
   2043 }
   2044 
   2045 void WebGLRenderingContext::uniform3iv(const WebGLUniformLocation* location, int* v, int size, ExceptionCode& ec)
   2046 {
   2047     UNUSED_PARAM(ec);
   2048     if (!location || location->program() != m_currentProgram) {
   2049         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
   2050         return;
   2051     }
   2052 
   2053     if (!v) {
   2054         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
   2055         return;
   2056     }
   2057     // FIXME: length needs to be a multiple of 3
   2058     m_context->uniform3iv(location->location(), v, size / 3);
   2059     cleanupAfterGraphicsCall(false);
   2060 }
   2061 
   2062 void WebGLRenderingContext::uniform4f(const WebGLUniformLocation* location, float x, float y, float z, float w, ExceptionCode& ec)
   2063 {
   2064     UNUSED_PARAM(ec);
   2065     if (!location || location->program() != m_currentProgram) {
   2066         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
   2067         return;
   2068     }
   2069 
   2070     m_context->uniform4f(location->location(), x, y, z, w);
   2071     cleanupAfterGraphicsCall(false);
   2072 }
   2073 
   2074 void WebGLRenderingContext::uniform4fv(const WebGLUniformLocation* location, WebGLFloatArray* v, ExceptionCode& ec)
   2075 {
   2076     UNUSED_PARAM(ec);
   2077     if (!location || location->program() != m_currentProgram) {
   2078         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
   2079         return;
   2080     }
   2081 
   2082     if (!v) {
   2083         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
   2084         return;
   2085     }
   2086     // FIXME: length needs to be a multiple of 4
   2087     m_context->uniform4fv(location->location(), v->data(), v->length() / 4);
   2088     cleanupAfterGraphicsCall(false);
   2089 }
   2090 
   2091 void WebGLRenderingContext::uniform4fv(const WebGLUniformLocation* location, float* v, int size, ExceptionCode& ec)
   2092 {
   2093     UNUSED_PARAM(ec);
   2094     if (!location || location->program() != m_currentProgram) {
   2095         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
   2096         return;
   2097     }
   2098 
   2099     if (!v) {
   2100         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
   2101         return;
   2102     }
   2103     // FIXME: length needs to be a multiple of 4
   2104     m_context->uniform4fv(location->location(), v, size / 4);
   2105     cleanupAfterGraphicsCall(false);
   2106 }
   2107 
   2108 void WebGLRenderingContext::uniform4i(const WebGLUniformLocation* location, int x, int y, int z, int w, ExceptionCode& ec)
   2109 {
   2110     UNUSED_PARAM(ec);
   2111     if (!location || location->program() != m_currentProgram) {
   2112         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
   2113         return;
   2114     }
   2115 
   2116     m_context->uniform4i(location->location(), x, y, z, w);
   2117     cleanupAfterGraphicsCall(false);
   2118 }
   2119 
   2120 void WebGLRenderingContext::uniform4iv(const WebGLUniformLocation* location, WebGLIntArray* v, ExceptionCode& ec)
   2121 {
   2122     UNUSED_PARAM(ec);
   2123     if (!location || location->program() != m_currentProgram) {
   2124         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
   2125         return;
   2126     }
   2127 
   2128     if (!v) {
   2129         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
   2130         return;
   2131     }
   2132     // FIXME: length needs to be a multiple of 4
   2133     m_context->uniform4iv(location->location(), v->data(), v->length() / 4);
   2134     cleanupAfterGraphicsCall(false);
   2135 }
   2136 
   2137 void WebGLRenderingContext::uniform4iv(const WebGLUniformLocation* location, int* v, int size, ExceptionCode& ec)
   2138 {
   2139     UNUSED_PARAM(ec);
   2140     if (!location || location->program() != m_currentProgram) {
   2141         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
   2142         return;
   2143     }
   2144 
   2145     if (!v) {
   2146         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
   2147         return;
   2148     }
   2149     // FIXME: length needs to be a multiple of 4
   2150     m_context->uniform4iv(location->location(), v, size / 4);
   2151     cleanupAfterGraphicsCall(false);
   2152 }
   2153 
   2154 void WebGLRenderingContext::uniformMatrix2fv(const WebGLUniformLocation* location, bool transpose, WebGLFloatArray* v, ExceptionCode& ec)
   2155 {
   2156     UNUSED_PARAM(ec);
   2157     if (!location || location->program() != m_currentProgram) {
   2158         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
   2159         return;
   2160     }
   2161 
   2162     if (!v) {
   2163         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
   2164         return;
   2165     }
   2166     // FIXME: length needs to be a multiple of 4
   2167     m_context->uniformMatrix2fv(location->location(), transpose, v->data(), v->length() / 4);
   2168     cleanupAfterGraphicsCall(false);
   2169 }
   2170 
   2171 void WebGLRenderingContext::uniformMatrix2fv(const WebGLUniformLocation* location, bool transpose, float* v, int size, ExceptionCode& ec)
   2172 {
   2173     UNUSED_PARAM(ec);
   2174     if (!location || location->program() != m_currentProgram) {
   2175         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
   2176         return;
   2177     }
   2178 
   2179     if (!v) {
   2180         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
   2181         return;
   2182     }
   2183     // FIXME: length needs to be a multiple of 4
   2184     m_context->uniformMatrix2fv(location->location(), transpose, v, size / 4);
   2185     cleanupAfterGraphicsCall(false);
   2186 }
   2187 
   2188 void WebGLRenderingContext::uniformMatrix3fv(const WebGLUniformLocation* location, bool transpose, WebGLFloatArray* v, ExceptionCode& ec)
   2189 {
   2190     UNUSED_PARAM(ec);
   2191     if (!location || location->program() != m_currentProgram) {
   2192         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
   2193         return;
   2194     }
   2195 
   2196     if (!v) {
   2197         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
   2198         return;
   2199     }
   2200     // FIXME: length needs to be a multiple of 9
   2201     m_context->uniformMatrix3fv(location->location(), transpose, v->data(), v->length() / 9);
   2202     cleanupAfterGraphicsCall(false);
   2203 }
   2204 
   2205 void WebGLRenderingContext::uniformMatrix3fv(const WebGLUniformLocation* location, bool transpose, float* v, int size, ExceptionCode& ec)
   2206 {
   2207     UNUSED_PARAM(ec);
   2208     if (!location || location->program() != m_currentProgram) {
   2209         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
   2210         return;
   2211     }
   2212 
   2213     if (!v) {
   2214         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
   2215         return;
   2216     }
   2217     // FIXME: length needs to be a multiple of 9
   2218     m_context->uniformMatrix3fv(location->location(), transpose, v, size / 9);
   2219     cleanupAfterGraphicsCall(false);
   2220 }
   2221 
   2222 void WebGLRenderingContext::uniformMatrix4fv(const WebGLUniformLocation* location, bool transpose, WebGLFloatArray* v, ExceptionCode& ec)
   2223 {
   2224     UNUSED_PARAM(ec);
   2225     if (!location || location->program() != m_currentProgram) {
   2226         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
   2227         return;
   2228     }
   2229 
   2230     if (!v) {
   2231         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
   2232         return;
   2233     }
   2234     // FIXME: length needs to be a multiple of 16
   2235     m_context->uniformMatrix4fv(location->location(), transpose, v->data(), v->length() / 16);
   2236     cleanupAfterGraphicsCall(false);
   2237 }
   2238 
   2239 void WebGLRenderingContext::uniformMatrix4fv(const WebGLUniformLocation* location, bool transpose, float* v, int size, ExceptionCode& ec)
   2240 {
   2241     UNUSED_PARAM(ec);
   2242     if (!location || location->program() != m_currentProgram) {
   2243         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
   2244         return;
   2245     }
   2246 
   2247     if (!v) {
   2248         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
   2249         return;
   2250     }
   2251     // FIXME: length needs to be a multiple of 16
   2252     m_context->uniformMatrix4fv(location->location(), transpose, v, size / 16);
   2253     cleanupAfterGraphicsCall(false);
   2254 }
   2255 
   2256 void WebGLRenderingContext::useProgram(WebGLProgram* program, ExceptionCode& ec)
   2257 {
   2258     UNUSED_PARAM(ec);
   2259     if (!program || program->context() != this) {
   2260         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
   2261         return;
   2262     }
   2263 
   2264     m_currentProgram = program;
   2265     m_context->useProgram(program);
   2266     cleanupAfterGraphicsCall(false);
   2267 }
   2268 
   2269 void WebGLRenderingContext::validateProgram(WebGLProgram* program, ExceptionCode& ec)
   2270 {
   2271     UNUSED_PARAM(ec);
   2272     if (!program || program->context() != this) {
   2273         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
   2274         return;
   2275     }
   2276 
   2277     m_context->validateProgram(program);
   2278     cleanupAfterGraphicsCall(false);
   2279 }
   2280 
   2281 void WebGLRenderingContext::vertexAttrib1f(unsigned long indx, float v0)
   2282 {
   2283     m_context->vertexAttrib1f(indx, v0);
   2284     cleanupAfterGraphicsCall(false);
   2285 }
   2286 
   2287 void WebGLRenderingContext::vertexAttrib1fv(unsigned long indx, WebGLFloatArray* v)
   2288 {
   2289     // FIXME: Need to make sure array is big enough for attribute being set
   2290     m_context->vertexAttrib1fv(indx, v->data());
   2291     cleanupAfterGraphicsCall(false);
   2292 }
   2293 
   2294 void WebGLRenderingContext::vertexAttrib1fv(unsigned long indx, float* v, int size)
   2295 {
   2296     // FIXME: Need to make sure array is big enough for attribute being set
   2297     UNUSED_PARAM(size);
   2298 
   2299     m_context->vertexAttrib1fv(indx, v);
   2300     cleanupAfterGraphicsCall(false);
   2301 }
   2302 
   2303 void WebGLRenderingContext::vertexAttrib2f(unsigned long indx, float v0, float v1)
   2304 {
   2305     m_context->vertexAttrib2f(indx, v0, v1);
   2306     cleanupAfterGraphicsCall(false);
   2307 }
   2308 
   2309 void WebGLRenderingContext::vertexAttrib2fv(unsigned long indx, WebGLFloatArray* v)
   2310 {
   2311     // FIXME: Need to make sure array is big enough for attribute being set
   2312     m_context->vertexAttrib2fv(indx, v->data());
   2313     cleanupAfterGraphicsCall(false);
   2314 }
   2315 
   2316 void WebGLRenderingContext::vertexAttrib2fv(unsigned long indx, float* v, int size)
   2317 {
   2318     // FIXME: Need to make sure array is big enough for attribute being set
   2319     UNUSED_PARAM(size);
   2320 
   2321     m_context->vertexAttrib2fv(indx, v);
   2322     cleanupAfterGraphicsCall(false);
   2323 }
   2324 
   2325 void WebGLRenderingContext::vertexAttrib3f(unsigned long indx, float v0, float v1, float v2)
   2326 {
   2327     m_context->vertexAttrib3f(indx, v0, v1, v2);
   2328     cleanupAfterGraphicsCall(false);
   2329 }
   2330 
   2331 void WebGLRenderingContext::vertexAttrib3fv(unsigned long indx, WebGLFloatArray* v)
   2332 {
   2333     // FIXME: Need to make sure array is big enough for attribute being set
   2334     m_context->vertexAttrib3fv(indx, v->data());
   2335     cleanupAfterGraphicsCall(false);
   2336 }
   2337 
   2338 void WebGLRenderingContext::vertexAttrib3fv(unsigned long indx, float* v, int size)
   2339 {
   2340     // FIXME: Need to make sure array is big enough for attribute being set
   2341     UNUSED_PARAM(size);
   2342 
   2343     m_context->vertexAttrib3fv(indx, v);
   2344     cleanupAfterGraphicsCall(false);
   2345 }
   2346 
   2347 void WebGLRenderingContext::vertexAttrib4f(unsigned long indx, float v0, float v1, float v2, float v3)
   2348 {
   2349     m_context->vertexAttrib4f(indx, v0, v1, v2, v3);
   2350     cleanupAfterGraphicsCall(false);
   2351 }
   2352 
   2353 void WebGLRenderingContext::vertexAttrib4fv(unsigned long indx, WebGLFloatArray* v)
   2354 {
   2355     // FIXME: Need to make sure array is big enough for attribute being set
   2356     m_context->vertexAttrib4fv(indx, v->data());
   2357     cleanupAfterGraphicsCall(false);
   2358 }
   2359 
   2360 void WebGLRenderingContext::vertexAttrib4fv(unsigned long indx, float* v, int size)
   2361 {
   2362     // FIXME: Need to make sure array is big enough for attribute being set
   2363     UNUSED_PARAM(size);
   2364 
   2365     m_context->vertexAttrib4fv(indx, v);
   2366     cleanupAfterGraphicsCall(false);
   2367 }
   2368 
   2369 void WebGLRenderingContext::vertexAttribPointer(unsigned long indx, long size, unsigned long type, bool normalized, unsigned long stride, unsigned long offset, ExceptionCode& ec)
   2370 {
   2371     UNUSED_PARAM(ec);
   2372     if (!m_boundArrayBuffer || indx >= m_maxVertexAttribs) {
   2373         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
   2374         return;
   2375     }
   2376 
   2377     if (indx >= m_vertexAttribState.size())
   2378         m_vertexAttribState.resize(indx + 1);
   2379 
   2380     // Determine the number of elements the bound buffer can hold, given the offset, size, type and stride
   2381     long bytesPerElement = size * sizeInBytes(type, ec);
   2382     if (bytesPerElement <= 0)
   2383         return;
   2384     long validatedStride = bytesPerElement;
   2385     if (stride != 0) {
   2386         if ((long) stride < bytesPerElement) {
   2387             m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
   2388             return;
   2389         }
   2390 
   2391         validatedStride = stride;
   2392     }
   2393 
   2394     // Avoid off-by-one errors in numElements computation.
   2395     // For the last element, we will only touch the data for the
   2396     // element and nothing beyond it.
   2397     long bytesRemaining = m_boundArrayBuffer->byteLength(GraphicsContext3D::ARRAY_BUFFER) - offset;
   2398     if (bytesRemaining < bytesPerElement)
   2399         m_vertexAttribState[indx].numElements = 0;
   2400     else
   2401         m_vertexAttribState[indx].numElements = 1 + (bytesRemaining - bytesPerElement) / validatedStride;
   2402 
   2403     m_context->vertexAttribPointer(indx, size, type, normalized, stride, offset);
   2404     cleanupAfterGraphicsCall(false);
   2405 }
   2406 
   2407 void WebGLRenderingContext::viewport(long x, long y, unsigned long width, unsigned long height)
   2408 {
   2409     if (isnan(x))
   2410         x = 0;
   2411     if (isnan(y))
   2412         y = 0;
   2413     if (isnan(width))
   2414         width = 100;
   2415     if (isnan(height))
   2416         height = 100;
   2417     m_context->viewport(x, y, width, height);
   2418     cleanupAfterGraphicsCall(false);
   2419 }
   2420 
   2421 void WebGLRenderingContext::removeObject(CanvasObject* object)
   2422 {
   2423     m_canvasObjects.remove(object);
   2424 }
   2425 
   2426 void WebGLRenderingContext::addObject(CanvasObject* object)
   2427 {
   2428     removeObject(object);
   2429     m_canvasObjects.add(object);
   2430 }
   2431 
   2432 void WebGLRenderingContext::detachAndRemoveAllObjects()
   2433 {
   2434     HashSet<RefPtr<CanvasObject> >::iterator pend = m_canvasObjects.end();
   2435     for (HashSet<RefPtr<CanvasObject> >::iterator it = m_canvasObjects.begin(); it != pend; ++it)
   2436         (*it)->detachContext();
   2437 
   2438     m_canvasObjects.clear();
   2439 }
   2440 
   2441 WebGLGetInfo WebGLRenderingContext::getBooleanParameter(unsigned long pname)
   2442 {
   2443     unsigned char value;
   2444     m_context->getBooleanv(pname, &value);
   2445     return WebGLGetInfo(static_cast<bool>(value));
   2446 }
   2447 
   2448 WebGLGetInfo WebGLRenderingContext::getFloatParameter(unsigned long pname)
   2449 {
   2450     float value;
   2451     m_context->getFloatv(pname, &value);
   2452     return WebGLGetInfo(static_cast<float>(value));
   2453 }
   2454 
   2455 WebGLGetInfo WebGLRenderingContext::getIntParameter(unsigned long pname)
   2456 {
   2457     return getLongParameter(pname);
   2458 }
   2459 
   2460 WebGLGetInfo WebGLRenderingContext::getLongParameter(unsigned long pname)
   2461 {
   2462     int value;
   2463     m_context->getIntegerv(pname, &value);
   2464     return WebGLGetInfo(static_cast<long>(value));
   2465 }
   2466 
   2467 WebGLGetInfo WebGLRenderingContext::getUnsignedLongParameter(unsigned long pname)
   2468 {
   2469     int value;
   2470     m_context->getIntegerv(pname, &value);
   2471     return WebGLGetInfo(static_cast<unsigned long>(value));
   2472 }
   2473 
   2474 WebGLGetInfo WebGLRenderingContext::getWebGLFloatArrayParameter(unsigned long pname)
   2475 {
   2476     float value[4] = {0};
   2477     m_context->getFloatv(pname, value);
   2478     unsigned length = 0;
   2479     switch (pname) {
   2480     case GraphicsContext3D::ALIASED_POINT_SIZE_RANGE:
   2481     case GraphicsContext3D::ALIASED_LINE_WIDTH_RANGE:
   2482     case GraphicsContext3D::DEPTH_RANGE:
   2483         length = 2;
   2484         break;
   2485     case GraphicsContext3D::BLEND_COLOR:
   2486     case GraphicsContext3D::COLOR_CLEAR_VALUE:
   2487         length = 4;
   2488         break;
   2489     default:
   2490         notImplemented();
   2491     }
   2492     return WebGLGetInfo(WebGLFloatArray::create(value, length));
   2493 }
   2494 
   2495 WebGLGetInfo WebGLRenderingContext::getWebGLIntArrayParameter(unsigned long pname)
   2496 {
   2497     int value[4] = {0};
   2498     m_context->getIntegerv(pname, value);
   2499     unsigned length = 0;
   2500     switch (pname) {
   2501     case GraphicsContext3D::MAX_VIEWPORT_DIMS:
   2502         length = 2;
   2503         break;
   2504     case GraphicsContext3D::SCISSOR_BOX:
   2505     case GraphicsContext3D::VIEWPORT:
   2506         length = 4;
   2507         break;
   2508     default:
   2509         notImplemented();
   2510     }
   2511     return WebGLGetInfo(WebGLIntArray::create(value, length));
   2512 }
   2513 
   2514 WebGLGetInfo WebGLRenderingContext::getWebGLUnsignedByteArrayParameter(unsigned long pname)
   2515 {
   2516     unsigned char value[4] = {0};
   2517     m_context->getBooleanv(pname, value);
   2518     unsigned length = 0;
   2519     switch (pname) {
   2520     case GraphicsContext3D::COLOR_WRITEMASK:
   2521         length = 4;
   2522         break;
   2523     default:
   2524         notImplemented();
   2525     }
   2526     return WebGLGetInfo(WebGLUnsignedByteArray::create(value, length));
   2527 }
   2528 
   2529 } // namespace WebCore
   2530 
   2531 #endif // ENABLE(3D_CANVAS)
   2532