2011-01-05 Adrienne Walker <enne@google.com>
[WebKit-https.git] / WebCore / html / canvas / WebGLRenderingContext.cpp
1 /*
2  * Copyright (C) 2009 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25
26 #include "config.h"
27
28 #if ENABLE(3D_CANVAS)
29
30 #include "WebGLRenderingContext.h"
31
32 #include "CachedImage.h"
33 #include "CanvasPixelArray.h"
34 #include "CheckedInt.h"
35 #include "WebKitLoseContext.h"
36 #include "Console.h"
37 #include "DOMWindow.h"
38 #include "Extensions3D.h"
39 #include "FrameView.h"
40 #include "HTMLCanvasElement.h"
41 #include "HTMLImageElement.h"
42 #include "HTMLVideoElement.h"
43 #include "ImageBuffer.h"
44 #include "ImageData.h"
45 #include "IntSize.h"
46 #include "NotImplemented.h"
47 #include "OESTextureFloat.h"
48 #include "RenderBox.h"
49 #include "RenderLayer.h"
50 #include "Uint16Array.h"
51 #include "WebGLActiveInfo.h"
52 #include "WebGLBuffer.h"
53 #include "WebGLContextAttributes.h"
54 #include "WebGLContextEvent.h"
55 #include "WebGLFramebuffer.h"
56 #include "WebGLProgram.h"
57 #include "WebGLRenderbuffer.h"
58 #include "WebGLShader.h"
59 #include "WebGLTexture.h"
60 #include "WebGLUniformLocation.h"
61
62 #include <wtf/ByteArray.h>
63 #include <wtf/OwnArrayPtr.h>
64 #include <wtf/PassOwnArrayPtr.h>
65
66 namespace WebCore {
67
68 const double secondsBetweenRestoreAttempts = 1.0;
69
70 namespace {
71
72     Platform3DObject objectOrZero(WebGLObject* object)
73     {
74         return object ? object->object() : 0;
75     }
76
77     void clip1D(long start, long range, long sourceRange, long* clippedStart, long* clippedRange)
78     {
79         ASSERT(clippedStart && clippedRange);
80         if (start < 0) {
81             range += start;
82             start = 0;
83         }
84         long end = start + range;
85         if (end > sourceRange)
86             range -= end - sourceRange;
87         *clippedStart = start;
88         *clippedRange = range;
89     }
90
91     // Returns false if no clipping is necessary, i.e., x, y, width, height stay the same.
92     bool clip2D(long x, long y, long width, long height,
93                 long sourceWidth, long sourceHeight,
94                 long* clippedX, long* clippedY, long* clippedWidth, long*clippedHeight)
95     {
96         ASSERT(clippedX && clippedY && clippedWidth && clippedHeight);
97         clip1D(x, width, sourceWidth, clippedX, clippedWidth);
98         clip1D(y, height, sourceHeight, clippedY, clippedHeight);
99         return (*clippedX != x || *clippedY != y || *clippedWidth != width || *clippedHeight != height);
100     }
101
102     // Return true if a character belongs to the ASCII subset as defined in
103     // GLSL ES 1.0 spec section 3.1.
104     bool validateCharacter(unsigned char c)
105     {
106         // Printing characters are valid except " $ ` @ \ ' DEL.
107         if (c >= 32 && c <= 126
108             && c != '"' && c != '$' && c != '`' && c != '@' && c != '\\' && c != '\'')
109             return true;
110         // Horizontal tab, line feed, vertical tab, form feed, carriage return
111         // are also valid.
112         if (c >= 9 && c <= 13)
113             return true;
114         return false;
115     }
116
117 } // namespace anonymous
118
119 class WebGLStateRestorer {
120 public:
121     WebGLStateRestorer(WebGLRenderingContext* context,
122                        bool changed)
123         : m_context(context)
124         , m_changed(changed)
125     {
126     }
127
128     ~WebGLStateRestorer()
129     {
130         m_context->cleanupAfterGraphicsCall(m_changed);
131     }
132
133 private:
134     WebGLRenderingContext* m_context;
135     bool m_changed;
136 };
137
138 void WebGLRenderingContext::WebGLRenderingContextRestoreTimer::fired()
139 {
140     // Timer is started when m_contextLost is false.  It will first call
141     // onLostContext, which will set m_contextLost to true.  Then it will keep
142     // calling restoreContext and reschedule itself until m_contextLost is back
143     // to false.
144     if (!m_context->m_contextLost) {
145         m_context->onLostContext();
146         startOneShot(secondsBetweenRestoreAttempts);
147     } else {
148         // The rendering context is not restored if there is no handler for
149         // the context restored event.
150         if (!m_context->canvas()->hasEventListeners(eventNames().webglcontextrestoredEvent))
151             return;
152
153         m_context->restoreContext();
154         if (m_context->m_contextLost)
155             startOneShot(secondsBetweenRestoreAttempts);
156     }
157 }
158
159 PassOwnPtr<WebGLRenderingContext> WebGLRenderingContext::create(HTMLCanvasElement* canvas, WebGLContextAttributes* attrs)
160 {
161     HostWindow* hostWindow = canvas->document()->view()->root()->hostWindow();
162     GraphicsContext3D::Attributes attributes = attrs ? attrs->attributes() : GraphicsContext3D::Attributes();
163     RefPtr<GraphicsContext3D> context(GraphicsContext3D::create(attributes, hostWindow));
164
165     if (!context) {
166         canvas->dispatchEvent(WebGLContextEvent::create(eventNames().webglcontextcreationerrorEvent, false, true, "Could not create a WebGL context."));
167         return 0;
168     }
169         
170     return new WebGLRenderingContext(canvas, context, attributes);
171 }
172
173 WebGLRenderingContext::WebGLRenderingContext(HTMLCanvasElement* passedCanvas, PassRefPtr<GraphicsContext3D> context,
174                                              GraphicsContext3D::Attributes attributes)
175     : CanvasRenderingContext(passedCanvas)
176     , m_context(context)
177     , m_restoreTimer(this)
178     , m_videoCache(4)
179     , m_contextLost(false)
180     , m_attributes(attributes)
181 {
182     ASSERT(m_context);
183     setupFlags();
184     initializeNewContext();
185 }
186
187 void WebGLRenderingContext::initializeNewContext()
188 {
189     ASSERT(!m_contextLost);
190     m_needsUpdate = true;
191     m_markedCanvasDirty = false;
192     m_activeTextureUnit = 0;
193     m_packAlignment = 4;
194     m_unpackAlignment = 4;
195     m_unpackFlipY = false;
196     m_unpackPremultiplyAlpha = false;
197     m_unpackColorspaceConversion = GraphicsContext3D::BROWSER_DEFAULT_WEBGL;
198     m_boundArrayBuffer = 0;
199     m_boundElementArrayBuffer = 0;
200     m_currentProgram = 0;
201     m_framebufferBinding = 0;
202     m_renderbufferBinding = 0;
203     m_stencilMask = 0xFFFFFFFF;
204     m_stencilMaskBack = 0xFFFFFFFF;
205     m_stencilFuncRef = 0;
206     m_stencilFuncRefBack = 0;
207     m_stencilFuncMask = 0xFFFFFFFF;
208     m_stencilFuncMaskBack = 0xFFFFFFFF;
209     m_vertexAttribState.clear();
210
211     int numCombinedTextureImageUnits = 0;
212     m_context->getIntegerv(GraphicsContext3D::MAX_COMBINED_TEXTURE_IMAGE_UNITS, &numCombinedTextureImageUnits);
213     m_textureUnits.clear();
214     m_textureUnits.resize(numCombinedTextureImageUnits);
215
216     int numVertexAttribs = 0;
217     m_context->getIntegerv(GraphicsContext3D::MAX_VERTEX_ATTRIBS, &numVertexAttribs);
218     m_maxVertexAttribs = numVertexAttribs;
219
220     m_maxTextureSize = 0;
221     m_context->getIntegerv(GraphicsContext3D::MAX_TEXTURE_SIZE, &m_maxTextureSize);
222     m_maxTextureLevel = WebGLTexture::computeLevelCount(m_maxTextureSize, m_maxTextureSize);
223     m_maxCubeMapTextureSize = 0;
224     m_context->getIntegerv(GraphicsContext3D::MAX_CUBE_MAP_TEXTURE_SIZE, &m_maxCubeMapTextureSize);
225     m_maxCubeMapTextureLevel = WebGLTexture::computeLevelCount(m_maxCubeMapTextureSize, m_maxCubeMapTextureSize);
226
227     if (!isGLES2NPOTStrict())
228         createFallbackBlackTextures1x1();
229     if (!isGLES2Compliant())
230         initVertexAttrib0();
231
232     m_context->reshape(canvas()->width(), canvas()->height());
233     m_context->viewport(0, 0, canvas()->width(), canvas()->height());
234 }
235
236 void WebGLRenderingContext::setupFlags()
237 {
238     ASSERT(m_context);
239
240     m_isGLES2Compliant = m_context->isGLES2Compliant();
241     m_isErrorGeneratedOnOutOfBoundsAccesses = m_context->getExtensions()->supports("GL_CHROMIUM_strict_attribs");
242     m_isResourceSafe = m_context->getExtensions()->supports("GL_CHROMIUM_resource_safe");
243     if (m_isGLES2Compliant) {
244         m_isGLES2NPOTStrict = !m_context->getExtensions()->supports("GL_OES_texture_npot");
245         m_isDepthStencilSupported = m_context->getExtensions()->supports("GL_OES_packed_depth_stencil");
246     } else {
247         m_isGLES2NPOTStrict = !m_context->getExtensions()->supports("GL_ARB_texture_non_power_of_two");
248         m_isDepthStencilSupported = m_context->getExtensions()->supports("GL_EXT_packed_depth_stencil");
249     }
250 }
251
252 WebGLRenderingContext::~WebGLRenderingContext()
253 {
254     detachAndRemoveAllObjects();
255 }
256
257 void WebGLRenderingContext::markContextChanged()
258 {
259 #if USE(ACCELERATED_COMPOSITING)
260     RenderBox* renderBox = canvas()->renderBox();
261     if (renderBox && renderBox->hasLayer() && renderBox->layer()->hasAcceleratedCompositing())
262         renderBox->layer()->contentChanged(RenderLayer::CanvasChanged);
263     else {
264 #endif
265         if (!m_markedCanvasDirty)
266             canvas()->didDraw(FloatRect(0, 0, canvas()->width(), canvas()->height()));
267 #if USE(ACCELERATED_COMPOSITING)
268     }
269 #endif
270     m_markedCanvasDirty = true;
271 }
272
273 void WebGLRenderingContext::paintRenderingResultsToCanvas()
274 {
275     if (!m_markedCanvasDirty)
276         return;
277     canvas()->clearCopiedImage();
278     m_markedCanvasDirty = false;
279     m_context->paintRenderingResultsToCanvas(this);
280 }
281
282 bool WebGLRenderingContext::paintsIntoCanvasBuffer() const
283 {
284     return m_context->paintsIntoCanvasBuffer();
285 }
286
287 void WebGLRenderingContext::reshape(int width, int height)
288 {
289     if (m_needsUpdate) {
290 #if USE(ACCELERATED_COMPOSITING)
291         RenderBox* renderBox = canvas()->renderBox();
292         if (renderBox && renderBox->hasLayer())
293             renderBox->layer()->contentChanged(RenderLayer::CanvasChanged);
294 #endif
295         m_needsUpdate = false;
296     }
297
298     // We don't have to mark the canvas as dirty, since the newly created image buffer will also start off
299     // clear (and this matches what reshape will do).
300     m_context->reshape(width, height);
301 }
302
303 int WebGLRenderingContext::sizeInBytes(int type)
304 {
305     return m_context->sizeInBytes(type);
306 }
307
308 void WebGLRenderingContext::activeTexture(unsigned long texture, ExceptionCode& ec)
309 {
310     UNUSED_PARAM(ec);
311     if (isContextLost())
312         return;
313     if (texture - GraphicsContext3D::TEXTURE0 >= m_textureUnits.size()) {
314         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
315         return;
316     }
317     m_activeTextureUnit = texture - GraphicsContext3D::TEXTURE0;
318     m_context->activeTexture(texture);
319     cleanupAfterGraphicsCall(false);
320 }
321
322 void WebGLRenderingContext::attachShader(WebGLProgram* program, WebGLShader* shader, ExceptionCode& ec)
323 {
324     UNUSED_PARAM(ec);
325     if (isContextLost() || !validateWebGLObject(program) || !validateWebGLObject(shader))
326         return;
327     if (!program->attachShader(shader)) {
328         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
329         return;
330     }
331     m_context->attachShader(objectOrZero(program), objectOrZero(shader));
332     shader->onAttached();
333     cleanupAfterGraphicsCall(false);
334 }
335
336 void WebGLRenderingContext::bindAttribLocation(WebGLProgram* program, unsigned long index, const String& name, ExceptionCode& ec)
337 {
338     UNUSED_PARAM(ec);
339     if (isContextLost() || !validateWebGLObject(program))
340         return;
341     if (!validateString(name))
342         return;
343     m_context->bindAttribLocation(objectOrZero(program), index, name);
344     cleanupAfterGraphicsCall(false);
345 }
346
347 void WebGLRenderingContext::bindBuffer(unsigned long target, WebGLBuffer* buffer, ExceptionCode& ec)
348 {
349     UNUSED_PARAM(ec);
350     if (isContextLost())
351         return;
352     if (buffer && buffer->context() != this) {
353         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
354         return;
355     }
356     if (buffer && buffer->getTarget() && buffer->getTarget() != target) {
357         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
358         return;
359     }
360
361     if (target == GraphicsContext3D::ARRAY_BUFFER)
362         m_boundArrayBuffer = buffer;
363     else if (target == GraphicsContext3D::ELEMENT_ARRAY_BUFFER)
364         m_boundElementArrayBuffer = buffer;
365     else {
366         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
367         return;
368     }
369
370     m_context->bindBuffer(target, objectOrZero(buffer));
371     if (buffer)
372         buffer->setTarget(target);
373     cleanupAfterGraphicsCall(false);
374 }
375
376
377 void WebGLRenderingContext::bindFramebuffer(unsigned long target, WebGLFramebuffer* buffer, ExceptionCode& ec)
378 {
379     UNUSED_PARAM(ec);
380     if (isContextLost())
381         return;
382     if (buffer && buffer->context() != this) {
383         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
384         return;
385     }
386     if (target != GraphicsContext3D::FRAMEBUFFER) {
387         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
388         return;
389     }
390     m_framebufferBinding = buffer;
391     m_context->bindFramebuffer(target, objectOrZero(buffer));
392     if (buffer)
393         buffer->setHasEverBeenBound();
394     cleanupAfterGraphicsCall(false);
395 }
396
397 void WebGLRenderingContext::bindRenderbuffer(unsigned long target, WebGLRenderbuffer* renderBuffer, ExceptionCode& ec)
398 {
399     UNUSED_PARAM(ec);
400     if (isContextLost())
401         return;
402     if (renderBuffer && renderBuffer->context() != this) {
403         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
404         return;
405     }
406     if (target != GraphicsContext3D::RENDERBUFFER) {
407         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
408         return;
409     }
410     m_renderbufferBinding = renderBuffer;
411     m_context->bindRenderbuffer(target, objectOrZero(renderBuffer));
412     if (renderBuffer)
413         renderBuffer->setHasEverBeenBound();
414     cleanupAfterGraphicsCall(false);
415 }
416
417
418 void WebGLRenderingContext::bindTexture(unsigned long target, WebGLTexture* texture, ExceptionCode& ec)
419 {
420     UNUSED_PARAM(ec);
421     if (isContextLost())
422         return;
423     if (texture && texture->context() != this) {
424         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
425         return;
426     }
427     int maxLevel = 0;
428     if (target == GraphicsContext3D::TEXTURE_2D) {
429         m_textureUnits[m_activeTextureUnit].m_texture2DBinding = texture;
430         maxLevel = m_maxTextureLevel;
431     } else if (target == GraphicsContext3D::TEXTURE_CUBE_MAP) {
432         m_textureUnits[m_activeTextureUnit].m_textureCubeMapBinding = texture;
433         maxLevel = m_maxCubeMapTextureLevel;
434     } else {
435         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
436         return;
437     }
438     m_context->bindTexture(target, objectOrZero(texture));
439     if (texture)
440         texture->setTarget(target, maxLevel);
441
442     // Note: previously we used to automatically set the TEXTURE_WRAP_R
443     // repeat mode to CLAMP_TO_EDGE for cube map textures, because OpenGL
444     // ES 2.0 doesn't expose this flag (a bug in the specification) and
445     // otherwise the application has no control over the seams in this
446     // dimension. However, it appears that supporting this properly on all
447     // platforms is fairly involved (will require a HashMap from texture ID
448     // in all ports), and we have not had any complaints, so the logic has
449     // been removed.
450
451     cleanupAfterGraphicsCall(false);
452 }
453
454 void WebGLRenderingContext::blendColor(float red, float green, float blue, float alpha)
455 {
456     if (isContextLost())
457         return;
458     m_context->blendColor(red, green, blue, alpha);
459     cleanupAfterGraphicsCall(false);
460 }
461
462 void WebGLRenderingContext::blendEquation(unsigned long mode)
463 {
464     if (isContextLost() || !validateBlendEquation(mode))
465         return;
466     m_context->blendEquation(mode);
467     cleanupAfterGraphicsCall(false);
468 }
469
470 void WebGLRenderingContext::blendEquationSeparate(unsigned long modeRGB, unsigned long modeAlpha)
471 {
472     if (isContextLost() || !validateBlendEquation(modeRGB) || !validateBlendEquation(modeAlpha))
473         return;
474     m_context->blendEquationSeparate(modeRGB, modeAlpha);
475     cleanupAfterGraphicsCall(false);
476 }
477
478
479 void WebGLRenderingContext::blendFunc(unsigned long sfactor, unsigned long dfactor)
480 {
481     if (isContextLost() || !validateBlendFuncFactors(sfactor, dfactor))
482         return;
483     m_context->blendFunc(sfactor, dfactor);
484     cleanupAfterGraphicsCall(false);
485 }       
486
487 void WebGLRenderingContext::blendFuncSeparate(unsigned long srcRGB, unsigned long dstRGB, unsigned long srcAlpha, unsigned long dstAlpha)
488 {
489     if (isContextLost() || !validateBlendFuncFactors(srcRGB, dstRGB))
490         return;
491     m_context->blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha);
492     cleanupAfterGraphicsCall(false);
493 }
494
495 void WebGLRenderingContext::bufferData(unsigned long target, int size, unsigned long usage, ExceptionCode& ec)
496 {
497     UNUSED_PARAM(ec);
498     if (isContextLost())
499         return;
500     WebGLBuffer* buffer = validateBufferDataParameters(target, usage);
501     if (!buffer)
502         return;
503     if (!isErrorGeneratedOnOutOfBoundsAccesses()) {
504         if (!buffer->associateBufferData(size)) {
505             m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
506             return;
507         }
508     }
509
510     m_context->bufferData(target, size, usage);
511     cleanupAfterGraphicsCall(false);
512 }
513
514 void WebGLRenderingContext::bufferData(unsigned long target, ArrayBuffer* data, unsigned long usage, ExceptionCode& ec)
515 {
516     UNUSED_PARAM(ec);
517     if (isContextLost())
518         return;
519     WebGLBuffer* buffer = validateBufferDataParameters(target, usage);
520     if (!buffer)
521         return;
522     if (!data) {
523         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
524         return;
525     }
526     if (!isErrorGeneratedOnOutOfBoundsAccesses()) {
527         if (!buffer->associateBufferData(data)) {
528             m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
529             return;
530         }
531     }
532
533     m_context->bufferData(target, data->byteLength(), data->data(), usage);
534     cleanupAfterGraphicsCall(false);
535 }
536
537 void WebGLRenderingContext::bufferData(unsigned long target, ArrayBufferView* data, unsigned long usage, ExceptionCode& ec)
538 {
539     UNUSED_PARAM(ec);
540     if (isContextLost())
541         return;
542     WebGLBuffer* buffer = validateBufferDataParameters(target, usage);
543     if (!buffer)
544         return;
545     if (!data) {
546         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
547         return;
548     }
549     if (!isErrorGeneratedOnOutOfBoundsAccesses()) {
550         if (!buffer->associateBufferData(data)) {
551             m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
552             return;
553         }
554     }
555
556     m_context->bufferData(target, data->byteLength(), data->baseAddress(), usage);
557     cleanupAfterGraphicsCall(false);
558 }
559
560 void WebGLRenderingContext::bufferSubData(unsigned long target, long offset, ArrayBuffer* data, ExceptionCode& ec)
561 {
562     UNUSED_PARAM(ec);
563     if (isContextLost())
564         return;
565     WebGLBuffer* buffer = validateBufferDataParameters(target, GraphicsContext3D::STATIC_DRAW);
566     if (!buffer)
567         return;
568     if (!data)
569         return;
570     if (!isErrorGeneratedOnOutOfBoundsAccesses()) {
571         if (!buffer->associateBufferSubData(offset, data)) {
572             m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
573             return;
574         }
575     }
576
577     m_context->bufferSubData(target, offset, data->byteLength(), data->data());
578     cleanupAfterGraphicsCall(false);
579 }
580
581 void WebGLRenderingContext::bufferSubData(unsigned long target, long offset, ArrayBufferView* data, ExceptionCode& ec)
582 {
583     UNUSED_PARAM(ec);
584     if (isContextLost())
585         return;
586     WebGLBuffer* buffer = validateBufferDataParameters(target, GraphicsContext3D::STATIC_DRAW);
587     if (!buffer)
588         return;
589     if (!data)
590         return;
591     if (!isErrorGeneratedOnOutOfBoundsAccesses()) {
592         if (!buffer->associateBufferSubData(offset, data)) {
593             m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
594             return;
595         }
596     }
597
598     m_context->bufferSubData(target, offset, data->byteLength(), data->baseAddress());
599     cleanupAfterGraphicsCall(false);
600 }
601
602 unsigned long WebGLRenderingContext::checkFramebufferStatus(unsigned long target)
603 {
604     if (isContextLost())
605         return GraphicsContext3D::FRAMEBUFFER_UNSUPPORTED;
606     if (target != GraphicsContext3D::FRAMEBUFFER) {
607         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
608         return 0;
609     }
610     if (!m_framebufferBinding || !m_framebufferBinding->object())
611         return GraphicsContext3D::FRAMEBUFFER_COMPLETE;
612     if (m_framebufferBinding->isIncomplete(true))
613         return GraphicsContext3D::FRAMEBUFFER_UNSUPPORTED;
614     unsigned long result = m_context->checkFramebufferStatus(target);
615     cleanupAfterGraphicsCall(false);
616     return result;
617 }
618
619 void WebGLRenderingContext::clear(unsigned long mask)
620 {
621     if (isContextLost())
622         return;
623     if (mask & ~(GraphicsContext3D::COLOR_BUFFER_BIT | GraphicsContext3D::DEPTH_BUFFER_BIT | GraphicsContext3D::STENCIL_BUFFER_BIT)) {
624         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
625         return;
626     }
627     if (m_framebufferBinding && !m_framebufferBinding->onAccess(!isResourceSafe())) {
628         m_context->synthesizeGLError(GraphicsContext3D::INVALID_FRAMEBUFFER_OPERATION);
629         return;
630     }
631     m_context->clear(mask);
632     cleanupAfterGraphicsCall(true);
633 }
634
635 void WebGLRenderingContext::clearColor(float r, float g, float b, float a)
636 {
637     if (isContextLost())
638         return;
639     if (isnan(r))
640         r = 0;
641     if (isnan(g))
642         g = 0;
643     if (isnan(b))
644         b = 0;
645     if (isnan(a))
646         a = 1;
647     m_context->clearColor(r, g, b, a);
648     cleanupAfterGraphicsCall(false);
649 }
650
651 void WebGLRenderingContext::clearDepth(float depth)
652 {
653     if (isContextLost())
654         return;
655     m_context->clearDepth(depth);
656     cleanupAfterGraphicsCall(false);
657 }
658
659 void WebGLRenderingContext::clearStencil(long s)
660 {
661     if (isContextLost())
662         return;
663     m_context->clearStencil(s);
664     cleanupAfterGraphicsCall(false);
665 }
666
667 void WebGLRenderingContext::colorMask(bool red, bool green, bool blue, bool alpha)
668 {
669     if (isContextLost())
670         return;
671     m_context->colorMask(red, green, blue, alpha);
672     cleanupAfterGraphicsCall(false);
673 }
674
675 void WebGLRenderingContext::compileShader(WebGLShader* shader, ExceptionCode& ec)
676 {
677     UNUSED_PARAM(ec);
678     if (isContextLost() || !validateWebGLObject(shader))
679         return;
680     m_context->compileShader(objectOrZero(shader));
681     cleanupAfterGraphicsCall(false);
682 }
683
684 void WebGLRenderingContext::copyTexImage2D(unsigned long target, long level, unsigned long internalformat, long x, long y, long width, long height, long border)
685 {
686     if (isContextLost())
687         return;
688     if (!validateTexFuncParameters(target, level, internalformat, width, height, border, internalformat, GraphicsContext3D::UNSIGNED_BYTE))
689         return;
690     WebGLTexture* tex = validateTextureBinding(target, true);
691     if (!tex)
692         return;
693     if (!isTexInternalFormatColorBufferCombinationValid(internalformat, getBoundFramebufferColorFormat())) {
694         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
695         return;
696     }
697     if (!isGLES2NPOTStrict() && level && WebGLTexture::isNPOT(width, height)) {
698         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
699         return;
700     }
701     if (m_framebufferBinding && !m_framebufferBinding->onAccess(!isResourceSafe())) {
702         m_context->synthesizeGLError(GraphicsContext3D::INVALID_FRAMEBUFFER_OPERATION);
703         return;
704     }
705     if (isResourceSafe())
706         m_context->copyTexImage2D(target, level, internalformat, x, y, width, height, border);
707     else {
708         long clippedX, clippedY, clippedWidth, clippedHeight;
709         if (clip2D(x, y, width, height, getBoundFramebufferWidth(), getBoundFramebufferHeight(), &clippedX, &clippedY, &clippedWidth, &clippedHeight)) {
710             m_context->texImage2DResourceSafe(target, level, internalformat, width, height, border,
711                                               internalformat, GraphicsContext3D::UNSIGNED_BYTE);
712             if (clippedWidth > 0 && clippedHeight > 0) {
713                 m_context->copyTexSubImage2D(target, level, clippedX - x, clippedY - y,
714                                              clippedX, clippedY, clippedWidth, clippedHeight);
715             }
716         } else
717             m_context->copyTexImage2D(target, level, internalformat, x, y, width, height, border);
718     }
719     // FIXME: if the framebuffer is not complete, none of the below should be executed.
720     tex->setLevelInfo(target, level, internalformat, width, height, GraphicsContext3D::UNSIGNED_BYTE);
721     cleanupAfterGraphicsCall(false);
722 }
723
724 void WebGLRenderingContext::copyTexSubImage2D(unsigned long target, long level, long xoffset, long yoffset, long x, long y, long width, long height)
725 {
726     if (isContextLost())
727         return;
728     if (!validateTexFuncLevel(target, level))
729         return;
730     WebGLTexture* tex = validateTextureBinding(target, true);
731     if (!tex)
732         return;
733     if (!validateSize(xoffset, yoffset) || !validateSize(width, height))
734         return;
735     if (xoffset + width > tex->getWidth(target, level) || yoffset + height > tex->getHeight(target, level)) {
736         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
737         return;
738     }
739     if (!isTexInternalFormatColorBufferCombinationValid(tex->getInternalFormat(target, level), getBoundFramebufferColorFormat())) {
740         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
741         return;
742     }
743     if (m_framebufferBinding && !m_framebufferBinding->onAccess(!isResourceSafe())) {
744         m_context->synthesizeGLError(GraphicsContext3D::INVALID_FRAMEBUFFER_OPERATION);
745         return;
746     }
747     if (isResourceSafe())
748         m_context->copyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height);
749     else {
750         long clippedX, clippedY, clippedWidth, clippedHeight;
751         if (clip2D(x, y, width, height, getBoundFramebufferWidth(), getBoundFramebufferHeight(), &clippedX, &clippedY, &clippedWidth, &clippedHeight)) {
752             unsigned long format = tex->getInternalFormat(target, level);
753             unsigned long type = tex->getType(target, level);
754             unsigned int componentsPerPixel = 0;
755             unsigned int bytesPerComponent = 0;
756             bool valid = m_context->computeFormatAndTypeParameters(format, type, &componentsPerPixel, &bytesPerComponent);
757             if (!valid) {
758                 m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
759                 return;
760             }
761             OwnArrayPtr<unsigned char> zero;
762             if (width && height) {
763                 unsigned long size = componentsPerPixel * bytesPerComponent * width * height;
764                 zero = adoptArrayPtr(new unsigned char[size]);
765                 if (!zero) {
766                     m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
767                     return;
768                 }
769                 memset(zero.get(), 0, size);
770             }
771             if (zero)
772                 m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, 1);
773             m_context->texSubImage2D(target, level, xoffset, yoffset, width, height, format, type, zero.get());
774             if (zero)
775                 m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, m_unpackAlignment);
776             if (clippedWidth > 0 && clippedHeight > 0) {
777                 m_context->copyTexSubImage2D(target, level, xoffset + clippedX - x, yoffset + clippedY - y,
778                                              clippedX, clippedY, clippedWidth, clippedHeight);
779             }
780         } else
781             m_context->copyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height);
782     }
783     cleanupAfterGraphicsCall(false);
784 }
785
786 PassRefPtr<WebGLBuffer> WebGLRenderingContext::createBuffer()
787 {
788     if (isContextLost())
789         return 0;
790     RefPtr<WebGLBuffer> o = WebGLBuffer::create(this);
791     addObject(o.get());
792     return o;
793 }
794         
795 PassRefPtr<WebGLFramebuffer> WebGLRenderingContext::createFramebuffer()
796 {
797     if (isContextLost())
798         return 0;
799     RefPtr<WebGLFramebuffer> o = WebGLFramebuffer::create(this);
800     addObject(o.get());
801     return o;
802 }
803
804 PassRefPtr<WebGLTexture> WebGLRenderingContext::createTexture()
805 {
806     if (isContextLost())
807         return 0;
808     RefPtr<WebGLTexture> o = WebGLTexture::create(this);
809     addObject(o.get());
810     return o;
811 }
812
813 PassRefPtr<WebGLProgram> WebGLRenderingContext::createProgram()
814 {
815     if (isContextLost())
816         return 0;
817     RefPtr<WebGLProgram> o = WebGLProgram::create(this);
818     addObject(o.get());
819     return o;
820 }
821
822 PassRefPtr<WebGLRenderbuffer> WebGLRenderingContext::createRenderbuffer()
823 {
824     if (isContextLost())
825         return 0;
826     RefPtr<WebGLRenderbuffer> o = WebGLRenderbuffer::create(this);
827     addObject(o.get());
828     return o;
829 }
830
831 PassRefPtr<WebGLShader> WebGLRenderingContext::createShader(unsigned long type, ExceptionCode& ec)
832 {
833     UNUSED_PARAM(ec);
834     if (isContextLost())
835         return 0;
836     if (type != GraphicsContext3D::VERTEX_SHADER && type != GraphicsContext3D::FRAGMENT_SHADER) {
837         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
838         return 0;
839     }
840     
841     RefPtr<WebGLShader> o = WebGLShader::create(this, static_cast<GraphicsContext3D::WebGLEnumType>(type));
842     addObject(o.get());
843     return o;
844 }
845
846 void WebGLRenderingContext::cullFace(unsigned long mode)
847 {
848     if (isContextLost())
849         return;
850     m_context->cullFace(mode);
851     cleanupAfterGraphicsCall(false);
852 }
853
854 void WebGLRenderingContext::deleteBuffer(WebGLBuffer* buffer)
855 {
856     if (isContextLost() || !buffer)
857         return;
858     
859     buffer->deleteObject();
860
861     if (!isGLES2Compliant()) {
862         VertexAttribState& state = m_vertexAttribState[0];
863         if (buffer == state.bufferBinding) {
864             state.bufferBinding = m_vertexAttrib0Buffer;
865             state.bytesPerElement = 0;
866             state.size = 4;
867             state.type = GraphicsContext3D::FLOAT;
868             state.normalized = false;
869             state.stride = 16;
870             state.originalStride = 0;
871             state.offset = 0;
872         }
873     }
874 }
875
876 void WebGLRenderingContext::deleteFramebuffer(WebGLFramebuffer* framebuffer)
877 {
878     if (isContextLost() || !framebuffer)
879         return;
880     if (framebuffer == m_framebufferBinding) {
881         m_framebufferBinding = 0;
882         // Have to call bindFramebuffer here to bind back to internal fbo.
883         m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, 0);
884     }
885     framebuffer->deleteObject();
886 }
887
888 void WebGLRenderingContext::deleteProgram(WebGLProgram* program)
889 {
890     if (isContextLost() || !program)
891         return;
892     if (program->context() != this) {
893         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
894         return;
895     }
896     if (!program->object())
897         return;
898     program->deleteObject();
899 }
900
901 void WebGLRenderingContext::deleteRenderbuffer(WebGLRenderbuffer* renderbuffer)
902 {
903     if (isContextLost() || !renderbuffer)
904         return;
905     if (renderbuffer == m_renderbufferBinding)
906         m_renderbufferBinding = 0;
907     renderbuffer->deleteObject();
908     if (m_framebufferBinding)
909         m_framebufferBinding->removeAttachment(renderbuffer);
910 }
911
912 void WebGLRenderingContext::deleteShader(WebGLShader* shader)
913 {
914     if (isContextLost() || !shader)
915         return;
916     
917     shader->deleteObject();
918 }
919
920 void WebGLRenderingContext::deleteTexture(WebGLTexture* texture)
921 {
922     if (isContextLost() || !texture)
923         return;
924     
925     texture->deleteObject();
926     if (m_framebufferBinding)
927         m_framebufferBinding->removeAttachment(texture);
928 }
929
930 void WebGLRenderingContext::depthFunc(unsigned long func)
931 {
932     if (isContextLost())
933         return;
934     m_context->depthFunc(func);
935     cleanupAfterGraphicsCall(false);
936 }
937
938 void WebGLRenderingContext::depthMask(bool flag)
939 {
940     if (isContextLost())
941         return;
942     m_context->depthMask(flag);
943     cleanupAfterGraphicsCall(false);
944 }
945
946 void WebGLRenderingContext::depthRange(float zNear, float zFar)
947 {
948     if (isContextLost())
949         return;
950     if (zNear > zFar) {
951         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
952         return;
953     }
954     m_context->depthRange(zNear, zFar);
955     cleanupAfterGraphicsCall(false);
956 }
957
958 void WebGLRenderingContext::detachShader(WebGLProgram* program, WebGLShader* shader, ExceptionCode& ec)
959 {
960     UNUSED_PARAM(ec);
961     if (isContextLost() || !validateWebGLObject(program) || !validateWebGLObject(shader))
962         return;
963     if (!program->detachShader(shader)) {
964         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
965         return;
966     }
967     m_context->detachShader(objectOrZero(program), objectOrZero(shader));
968     shader->onDetached();
969     cleanupAfterGraphicsCall(false);
970 }
971
972
973 void WebGLRenderingContext::disable(unsigned long cap)
974 {
975     if (isContextLost() || !validateCapability(cap))
976         return;
977     m_context->disable(cap);
978     cleanupAfterGraphicsCall(false);
979 }
980
981 void WebGLRenderingContext::disableVertexAttribArray(unsigned long index, ExceptionCode& ec)
982 {
983     UNUSED_PARAM(ec);
984     if (isContextLost())
985         return;
986     if (index >= m_maxVertexAttribs) {
987         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
988         return;
989     }
990     
991     if (index < m_vertexAttribState.size())
992         m_vertexAttribState[index].enabled = false;
993
994     if (index > 0 || isGLES2Compliant()) {
995         m_context->disableVertexAttribArray(index);
996         cleanupAfterGraphicsCall(false);
997     }
998 }
999
1000 bool WebGLRenderingContext::validateElementArraySize(unsigned long count, unsigned long type, long offset)
1001 {
1002     if (!m_boundElementArrayBuffer)
1003         return false;
1004
1005     if (offset < 0)
1006         return false;
1007
1008     unsigned long uoffset = static_cast<unsigned long>(offset);
1009
1010     if (type == GraphicsContext3D::UNSIGNED_SHORT) {
1011         // For an unsigned short array, offset must be divisible by 2 for alignment reasons.
1012         if (uoffset & 1)
1013             return false;
1014
1015         // Make uoffset an element offset.
1016         uoffset /= 2;
1017
1018         unsigned long n = m_boundElementArrayBuffer->byteLength() / 2;
1019         if (uoffset > n || count > n - uoffset)
1020             return false;
1021     } else if (type == GraphicsContext3D::UNSIGNED_BYTE) {
1022         unsigned long n = m_boundElementArrayBuffer->byteLength();
1023         if (uoffset > n || count > n - uoffset)
1024             return false;
1025     }
1026     return true;
1027 }
1028
1029 bool WebGLRenderingContext::validateIndexArrayConservative(unsigned long type, long& numElementsRequired)
1030 {
1031     // Performs conservative validation by caching a maximum index of
1032     // the given type per element array buffer. If all of the bound
1033     // array buffers have enough elements to satisfy that maximum
1034     // index, skips the expensive per-draw-call iteration in
1035     // validateIndexArrayPrecise.
1036
1037     if (!m_boundElementArrayBuffer)
1038         return false;
1039
1040     unsigned numElements = m_boundElementArrayBuffer->byteLength();
1041     // The case count==0 is already dealt with in drawElements before validateIndexArrayConservative.
1042     if (!numElements)
1043         return false;
1044     const ArrayBuffer* buffer = m_boundElementArrayBuffer->elementArrayBuffer();
1045     ASSERT(buffer);
1046
1047     long maxIndex = m_boundElementArrayBuffer->getCachedMaxIndex(type);
1048     if (maxIndex < 0) {
1049         // Compute the maximum index in the entire buffer for the given type of index.
1050         switch (type) {
1051         case GraphicsContext3D::UNSIGNED_BYTE: {
1052             const unsigned char* p = static_cast<const unsigned char*>(buffer->data());
1053             for (unsigned i = 0; i < numElements; i++)
1054                 maxIndex = max(maxIndex, static_cast<long>(p[i]));
1055             break;
1056         }
1057         case GraphicsContext3D::UNSIGNED_SHORT: {
1058             numElements /= sizeof(unsigned short);
1059             const unsigned short* p = static_cast<const unsigned short*>(buffer->data());
1060             for (unsigned i = 0; i < numElements; i++)
1061                 maxIndex = max(maxIndex, static_cast<long>(p[i]));
1062             break;
1063         }
1064         default:
1065             return false;
1066         }
1067         m_boundElementArrayBuffer->setCachedMaxIndex(type, maxIndex);
1068     }
1069
1070     if (maxIndex >= 0) {
1071         // The number of required elements is one more than the maximum
1072         // index that will be accessed.
1073         numElementsRequired = maxIndex + 1;
1074         return true;
1075     }
1076
1077     return false;
1078 }
1079
1080 bool WebGLRenderingContext::validateIndexArrayPrecise(unsigned long count, unsigned long type, long offset, long& numElementsRequired)
1081 {
1082     long lastIndex = -1;
1083
1084     if (!m_boundElementArrayBuffer)
1085         return false;
1086
1087     if (!count) {
1088         numElementsRequired = 0;
1089         return true;
1090     }
1091
1092     if (!m_boundElementArrayBuffer->elementArrayBuffer())
1093         return false;
1094
1095     unsigned long uoffset = static_cast<unsigned long>(offset);
1096     unsigned long n = count;
1097
1098     if (type == GraphicsContext3D::UNSIGNED_SHORT) {
1099         // Make uoffset an element offset.
1100         uoffset /= 2;
1101         const unsigned short* p = static_cast<const unsigned short*>(m_boundElementArrayBuffer->elementArrayBuffer()->data()) + uoffset;
1102         while (n-- > 0) {
1103             if (*p > lastIndex)
1104                 lastIndex = *p;
1105             ++p;
1106         }
1107     } else if (type == GraphicsContext3D::UNSIGNED_BYTE) {
1108         const unsigned char* p = static_cast<const unsigned char*>(m_boundElementArrayBuffer->elementArrayBuffer()->data()) + uoffset;
1109         while (n-- > 0) {
1110             if (*p > lastIndex)
1111                 lastIndex = *p;
1112             ++p;
1113         }
1114     }    
1115         
1116     // Then set the last index in the index array and make sure it is valid.
1117     numElementsRequired = lastIndex + 1;
1118     return numElementsRequired > 0;
1119 }
1120
1121 bool WebGLRenderingContext::validateRenderingState(long numElementsRequired)
1122 {
1123     if (!m_currentProgram)
1124         return false;
1125
1126     int numAttribStates = static_cast<int>(m_vertexAttribState.size());
1127
1128     // Look in each enabled vertex attrib and check if they've been bound to a buffer.
1129     for (int i = 0; i < numAttribStates; ++i) {
1130         if (m_vertexAttribState[i].enabled
1131             && (!m_vertexAttribState[i].bufferBinding || !m_vertexAttribState[i].bufferBinding->object()))
1132             return false;
1133     }
1134
1135     if (numElementsRequired <= 0)
1136         return true;
1137
1138     // Look in each consumed vertex attrib (by the current program) and find the smallest buffer size
1139     long smallestNumElements = LONG_MAX;
1140     int numActiveAttribLocations = m_currentProgram->numActiveAttribLocations();
1141     for (int i = 0; i < numActiveAttribLocations; ++i) {
1142         int loc = m_currentProgram->getActiveAttribLocation(i);
1143         if (loc >=0 && loc < numAttribStates) {
1144             const VertexAttribState& state = m_vertexAttribState[loc];
1145             if (state.enabled) {
1146                 // Avoid off-by-one errors in numElements computation.
1147                 // For the last element, we will only touch the data for the
1148                 // element and nothing beyond it.
1149                 long bytesRemaining = state.bufferBinding->byteLength() - state.offset;
1150                 long numElements = 0;
1151                 if (bytesRemaining >= state.bytesPerElement)
1152                     numElements = 1 + (bytesRemaining - state.bytesPerElement) / state.stride;
1153                 if (numElements < smallestNumElements)
1154                     smallestNumElements = numElements;
1155             }
1156         }
1157     }
1158     
1159     if (smallestNumElements == LONG_MAX)
1160         smallestNumElements = 0;
1161     
1162     return numElementsRequired <= smallestNumElements;
1163 }
1164
1165 bool WebGLRenderingContext::validateWebGLObject(WebGLObject* object)
1166 {
1167     if (!object || !object->object()) {
1168         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
1169         return false;
1170     }
1171     if (object->context() != this) {
1172         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
1173         return false;
1174     }
1175     return true;
1176 }
1177
1178 void WebGLRenderingContext::drawArrays(unsigned long mode, long first, long count, ExceptionCode& ec)
1179 {
1180     UNUSED_PARAM(ec);
1181
1182     if (isContextLost() || !validateDrawMode(mode))
1183         return;
1184
1185     if (!validateStencilSettings())
1186         return;
1187
1188     if (first < 0 || count < 0) {
1189         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
1190         return;
1191     }
1192
1193     if (!count)
1194         return;
1195
1196     if (!isErrorGeneratedOnOutOfBoundsAccesses()) {
1197         // Ensure we have a valid rendering state
1198         CheckedInt<int32_t> checkedFirst(first);
1199         CheckedInt<int32_t> checkedCount(count);
1200         CheckedInt<int32_t> checkedSum = checkedFirst + checkedCount;
1201         if (!checkedSum.valid() || !validateRenderingState(checkedSum.value())) {
1202             m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
1203             return;
1204         }
1205     } else {
1206         if (!validateRenderingState(0)) {
1207             m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
1208             return;
1209         }
1210     }
1211
1212     if (m_framebufferBinding && !m_framebufferBinding->onAccess(!isResourceSafe())) {
1213         m_context->synthesizeGLError(GraphicsContext3D::INVALID_FRAMEBUFFER_OPERATION);
1214         return;
1215     }
1216
1217     bool vertexAttrib0Simulated = false;
1218     if (!isGLES2Compliant())
1219         vertexAttrib0Simulated = simulateVertexAttrib0(first + count - 1);
1220     if (!isGLES2NPOTStrict())
1221         handleNPOTTextures(true);
1222     m_context->drawArrays(mode, first, count);
1223     if (!isGLES2Compliant() && vertexAttrib0Simulated)
1224         restoreStatesAfterVertexAttrib0Simulation();
1225     if (!isGLES2NPOTStrict())
1226         handleNPOTTextures(false);
1227     cleanupAfterGraphicsCall(true);
1228 }
1229
1230 void WebGLRenderingContext::drawElements(unsigned long mode, long count, unsigned long type, long offset, ExceptionCode& ec)
1231 {
1232     UNUSED_PARAM(ec);
1233
1234     if (isContextLost() || !validateDrawMode(mode))
1235         return;
1236
1237     if (!validateStencilSettings())
1238         return;
1239
1240     switch (type) {
1241     case GraphicsContext3D::UNSIGNED_BYTE:
1242     case GraphicsContext3D::UNSIGNED_SHORT:
1243         break;
1244     default:
1245         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
1246         return;
1247     }
1248
1249     if (count < 0 || offset < 0) {
1250         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
1251         return;
1252     }
1253
1254     if (!count)
1255         return;
1256
1257     long numElements = 0;
1258     if (!isErrorGeneratedOnOutOfBoundsAccesses()) {
1259         // Ensure we have a valid rendering state
1260         if (!validateElementArraySize(count, type, offset)) {
1261             m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
1262             return;
1263         }
1264         if (!count)
1265             return;
1266         if (!validateIndexArrayConservative(type, numElements) || !validateRenderingState(numElements)) {
1267             if (!validateIndexArrayPrecise(count, type, offset, numElements) || !validateRenderingState(numElements)) {
1268                 m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
1269                 return;
1270             }
1271         }
1272     } else {
1273         if (!validateRenderingState(0)) {
1274             m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
1275             return;
1276         }
1277     }
1278
1279     if (m_framebufferBinding && !m_framebufferBinding->onAccess(!isResourceSafe())) {
1280         m_context->synthesizeGLError(GraphicsContext3D::INVALID_FRAMEBUFFER_OPERATION);
1281         return;
1282     }
1283
1284     bool vertexAttrib0Simulated = false;
1285     if (!isGLES2Compliant()) {
1286         if (!numElements)
1287             validateIndexArrayPrecise(count, type, offset, numElements);
1288         vertexAttrib0Simulated = simulateVertexAttrib0(numElements);
1289     }
1290     if (!isGLES2NPOTStrict())
1291         handleNPOTTextures(true);
1292     m_context->drawElements(mode, count, type, offset);
1293     if (!isGLES2Compliant() && vertexAttrib0Simulated)
1294         restoreStatesAfterVertexAttrib0Simulation();
1295     if (!isGLES2NPOTStrict())
1296         handleNPOTTextures(false);
1297     cleanupAfterGraphicsCall(true);
1298 }
1299
1300 void WebGLRenderingContext::enable(unsigned long cap)
1301 {
1302     if (isContextLost() || !validateCapability(cap))
1303         return;
1304     m_context->enable(cap);
1305     cleanupAfterGraphicsCall(false);
1306 }
1307
1308 void WebGLRenderingContext::enableVertexAttribArray(unsigned long index, ExceptionCode& ec)
1309 {
1310     UNUSED_PARAM(ec);
1311     if (isContextLost())
1312         return;
1313     if (index >= m_maxVertexAttribs) {
1314         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
1315         return;
1316     }
1317     
1318     if (index >= m_vertexAttribState.size())
1319         m_vertexAttribState.resize(index + 1);
1320         
1321     m_vertexAttribState[index].enabled = true;
1322     
1323     m_context->enableVertexAttribArray(index);
1324     cleanupAfterGraphicsCall(false);
1325 }
1326
1327 void WebGLRenderingContext::finish()
1328 {
1329     if (isContextLost())
1330         return;
1331     m_context->finish();
1332     cleanupAfterGraphicsCall(true);
1333 }
1334
1335
1336 void WebGLRenderingContext::flush()
1337 {
1338     if (isContextLost())
1339         return;
1340     m_context->flush();
1341     cleanupAfterGraphicsCall(true);
1342 }
1343
1344 void WebGLRenderingContext::framebufferRenderbuffer(unsigned long target, unsigned long attachment, unsigned long renderbuffertarget, WebGLRenderbuffer* buffer, ExceptionCode& ec)
1345 {
1346     UNUSED_PARAM(ec);
1347     if (isContextLost() || !validateFramebufferFuncParameters(target, attachment))
1348         return;
1349     if (renderbuffertarget != GraphicsContext3D::RENDERBUFFER) {
1350         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
1351         return;
1352     }
1353     if (buffer && buffer->context() != this) {
1354         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
1355         return;
1356     }
1357     // Don't allow the default framebuffer to be mutated; all current
1358     // implementations use an FBO internally in place of the default
1359     // FBO.
1360     if (!m_framebufferBinding || !m_framebufferBinding->object()) {
1361         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
1362         return;
1363     }
1364     Platform3DObject bufferObject = objectOrZero(buffer);
1365     bool reattachDepth = false;
1366     bool reattachStencil = false;
1367     bool reattachDepthStencilDepth = false;
1368     bool reattachDepthStencilStencil = false;
1369     switch (attachment) {
1370     case GraphicsContext3D::DEPTH_STENCIL_ATTACHMENT:
1371         m_context->framebufferRenderbuffer(target, GraphicsContext3D::DEPTH_ATTACHMENT, renderbuffertarget, bufferObject);
1372         m_context->framebufferRenderbuffer(target, GraphicsContext3D::STENCIL_ATTACHMENT, renderbuffertarget, bufferObject);
1373         if (!bufferObject) {
1374             reattachDepth = true;
1375             reattachStencil = true;
1376         }
1377         break;
1378     case GraphicsContext3D::DEPTH_ATTACHMENT:
1379         m_context->framebufferRenderbuffer(target, attachment, renderbuffertarget, objectOrZero(buffer));
1380         if (!bufferObject)
1381             reattachDepthStencilDepth = true;
1382         break;
1383     case GraphicsContext3D::STENCIL_ATTACHMENT:
1384         m_context->framebufferRenderbuffer(target, attachment, renderbuffertarget, objectOrZero(buffer));
1385         if (!bufferObject)
1386             reattachDepthStencilStencil = true;
1387         break;
1388     default:
1389         m_context->framebufferRenderbuffer(target, attachment, renderbuffertarget, objectOrZero(buffer));
1390     }
1391     m_framebufferBinding->setAttachment(attachment, buffer);
1392     if (reattachDepth) {
1393         Platform3DObject object = objectOrZero(m_framebufferBinding->getAttachment(GraphicsContext3D::DEPTH_ATTACHMENT));
1394         if (object)
1395             m_context->framebufferRenderbuffer(target, GraphicsContext3D::DEPTH_ATTACHMENT, renderbuffertarget, object);
1396     }
1397     if (reattachStencil) {
1398         Platform3DObject object = objectOrZero(m_framebufferBinding->getAttachment(GraphicsContext3D::STENCIL_ATTACHMENT));
1399         if (object)
1400             m_context->framebufferRenderbuffer(target, GraphicsContext3D::STENCIL_ATTACHMENT, renderbuffertarget, object);
1401     }
1402     if (reattachDepthStencilDepth) {
1403         Platform3DObject object = objectOrZero(m_framebufferBinding->getAttachment(GraphicsContext3D::DEPTH_STENCIL_ATTACHMENT));
1404         if (object)
1405             m_context->framebufferRenderbuffer(target, GraphicsContext3D::DEPTH_ATTACHMENT, renderbuffertarget, object);
1406     }
1407     if (reattachDepthStencilStencil) {
1408         Platform3DObject object = objectOrZero(m_framebufferBinding->getAttachment(GraphicsContext3D::DEPTH_STENCIL_ATTACHMENT));
1409         if (object)
1410             m_context->framebufferRenderbuffer(target, GraphicsContext3D::STENCIL_ATTACHMENT, renderbuffertarget, object);
1411     }
1412     cleanupAfterGraphicsCall(false);
1413 }
1414
1415 void WebGLRenderingContext::framebufferTexture2D(unsigned long target, unsigned long attachment, unsigned long textarget, WebGLTexture* texture, long level, ExceptionCode& ec)
1416 {
1417     UNUSED_PARAM(ec);
1418     if (isContextLost() || !validateFramebufferFuncParameters(target, attachment))
1419         return;
1420     if (level) {
1421         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
1422         return;
1423     }
1424     if (texture && texture->context() != this) {
1425         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
1426         return;
1427     }
1428     // Don't allow the default framebuffer to be mutated; all current
1429     // implementations use an FBO internally in place of the default
1430     // FBO.
1431     if (!m_framebufferBinding || !m_framebufferBinding->object()) {
1432         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
1433         return;
1434     }
1435     m_context->framebufferTexture2D(target, attachment, textarget, objectOrZero(texture), level);
1436     m_framebufferBinding->setAttachment(attachment, textarget, texture, level);
1437     cleanupAfterGraphicsCall(false);
1438 }
1439
1440 void WebGLRenderingContext::frontFace(unsigned long mode)
1441 {
1442     if (isContextLost())
1443         return;
1444     m_context->frontFace(mode);
1445     cleanupAfterGraphicsCall(false);
1446 }
1447
1448 void WebGLRenderingContext::generateMipmap(unsigned long target)
1449 {
1450     if (isContextLost())
1451         return;
1452     WebGLTexture* tex = validateTextureBinding(target, false);
1453     if (!tex)
1454         return;
1455     if (!tex->canGenerateMipmaps()) {
1456         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
1457         return;
1458     }
1459     // generateMipmap won't work properly if minFilter is not NEAREST_MIPMAP_LINEAR
1460     // on Mac.  Remove the hack once this driver bug is fixed.
1461 #if OS(DARWIN)
1462     bool needToResetMinFilter = false;
1463     if (tex->getMinFilter() != GraphicsContext3D::NEAREST_MIPMAP_LINEAR) {
1464         m_context->texParameteri(target, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::NEAREST_MIPMAP_LINEAR);
1465         needToResetMinFilter = true;
1466     }
1467 #endif
1468     m_context->generateMipmap(target);
1469 #if OS(DARWIN)
1470     if (needToResetMinFilter)
1471         m_context->texParameteri(target, GraphicsContext3D::TEXTURE_MIN_FILTER, tex->getMinFilter());
1472 #endif
1473     tex->generateMipmapLevelInfo();
1474     cleanupAfterGraphicsCall(false);
1475 }
1476
1477 PassRefPtr<WebGLActiveInfo> WebGLRenderingContext::getActiveAttrib(WebGLProgram* program, unsigned long index, ExceptionCode& ec)
1478 {
1479     UNUSED_PARAM(ec);
1480     if (isContextLost() || !validateWebGLObject(program))
1481         return 0;
1482     ActiveInfo info;
1483     if (!m_context->getActiveAttrib(objectOrZero(program), index, info))
1484         return 0;
1485     return WebGLActiveInfo::create(info.name, info.type, info.size);
1486 }
1487
1488 PassRefPtr<WebGLActiveInfo> WebGLRenderingContext::getActiveUniform(WebGLProgram* program, unsigned long index, ExceptionCode& ec)
1489 {
1490     UNUSED_PARAM(ec);
1491     if (isContextLost() || !validateWebGLObject(program))
1492         return 0;
1493     ActiveInfo info;
1494     if (!m_context->getActiveUniform(objectOrZero(program), index, info))
1495         return 0;
1496     if (!isGLES2Compliant())
1497         if (info.size > 1 && !info.name.endsWith("[0]"))
1498             info.name.append("[0]");
1499     return WebGLActiveInfo::create(info.name, info.type, info.size);
1500 }
1501
1502 bool WebGLRenderingContext::getAttachedShaders(WebGLProgram* program, Vector<WebGLShader*>& shaderObjects, ExceptionCode& ec)
1503 {
1504     UNUSED_PARAM(ec);
1505     shaderObjects.clear();
1506     if (isContextLost() || !validateWebGLObject(program))
1507         return false;
1508     int numShaders = 0;
1509     m_context->getProgramiv(objectOrZero(program), GraphicsContext3D::ATTACHED_SHADERS, &numShaders);
1510     if (numShaders) {
1511         OwnArrayPtr<unsigned int> shaders(new unsigned int[numShaders]);
1512         int count = 0;
1513         m_context->getAttachedShaders(objectOrZero(program), numShaders, &count, shaders.get());
1514         if (count != numShaders)
1515             return false;
1516         shaderObjects.resize(numShaders);
1517         for (int ii = 0; ii < numShaders; ++ii) {
1518             WebGLShader* shader = findShader(shaders[ii]);
1519             if (!shader) {
1520                 shaderObjects.clear();
1521                 return false;
1522             }
1523             shaderObjects[ii] = shader;
1524         }
1525     }
1526     return true;
1527 }
1528
1529 int WebGLRenderingContext::getAttribLocation(WebGLProgram* program, const String& name)
1530 {
1531     if (isContextLost())
1532         return -1;
1533     if (!validateString(name))
1534         return -1;
1535     return m_context->getAttribLocation(objectOrZero(program), name);
1536 }
1537
1538 WebGLGetInfo WebGLRenderingContext::getBufferParameter(unsigned long target, unsigned long pname, ExceptionCode& ec)
1539 {
1540     UNUSED_PARAM(ec);
1541     if (isContextLost())
1542         return WebGLGetInfo();
1543     if (target != GraphicsContext3D::ARRAY_BUFFER && target != GraphicsContext3D::ELEMENT_ARRAY_BUFFER) {
1544         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
1545         return WebGLGetInfo();
1546     }
1547
1548     if (pname != GraphicsContext3D::BUFFER_SIZE && pname != GraphicsContext3D::BUFFER_USAGE) {
1549         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
1550         return WebGLGetInfo();
1551     }
1552
1553     WebGLStateRestorer(this, false);
1554     int value = 0;
1555     m_context->getBufferParameteriv(target, pname, &value);
1556     if (pname == GraphicsContext3D::BUFFER_SIZE)
1557         return WebGLGetInfo(static_cast<long>(value));
1558     return WebGLGetInfo(static_cast<unsigned long>(value));
1559 }
1560
1561 PassRefPtr<WebGLContextAttributes> WebGLRenderingContext::getContextAttributes()
1562 {
1563     if (isContextLost())
1564         return 0;
1565     // We always need to return a new WebGLContextAttributes object to
1566     // prevent the user from mutating any cached version.
1567     return WebGLContextAttributes::create(m_context->getContextAttributes());
1568 }
1569
1570 unsigned long WebGLRenderingContext::getError()
1571 {
1572     return m_context->getError();
1573 }
1574
1575 WebGLExtension* WebGLRenderingContext::getExtension(const String& name)
1576 {
1577     if (isContextLost())
1578         return 0;
1579
1580     if (equalIgnoringCase(name, "OES_texture_float")
1581         && m_context->getExtensions()->supports("GL_OES_texture_float")) {
1582         if (!m_oesTextureFloat) {
1583             m_context->getExtensions()->ensureEnabled("GL_OES_texture_float");
1584             m_oesTextureFloat = OESTextureFloat::create();
1585         }
1586         return m_oesTextureFloat.get();
1587     } else if (equalIgnoringCase(name, "WEBKIT_lose_context")) {
1588         if (!m_webkitLoseContext)
1589             m_webkitLoseContext = WebKitLoseContext::create(this);
1590         return m_webkitLoseContext.get();
1591     }
1592
1593     return 0;
1594 }
1595
1596 WebGLGetInfo WebGLRenderingContext::getFramebufferAttachmentParameter(unsigned long target, unsigned long attachment, unsigned long pname, ExceptionCode& ec)
1597 {
1598     UNUSED_PARAM(ec);
1599     if (isContextLost() || !validateFramebufferFuncParameters(target, attachment))
1600         return WebGLGetInfo();
1601     switch (pname) {
1602     case GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
1603     case GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
1604     case GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
1605     case GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
1606         break;
1607     default:
1608         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
1609         return WebGLGetInfo();
1610     }
1611
1612     if (!m_framebufferBinding || !m_framebufferBinding->object() || m_framebufferBinding->isIncomplete(false)) {
1613         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
1614         return WebGLGetInfo();
1615     }
1616
1617     if (pname != GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_OBJECT_NAME) {
1618         WebGLStateRestorer(this, false);
1619         int value = 0;
1620         m_context->getFramebufferAttachmentParameteriv(target, attachment, pname, &value);
1621         if (pname == GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE)
1622             return WebGLGetInfo(static_cast<unsigned long>(value));
1623         return WebGLGetInfo(static_cast<long>(value));
1624     }
1625
1626     WebGLStateRestorer(this, false);
1627     int type = 0;
1628     m_context->getFramebufferAttachmentParameteriv(target, attachment, GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &type);
1629     if (!type)
1630         return WebGLGetInfo();
1631     int value = 0;
1632     m_context->getFramebufferAttachmentParameteriv(target, attachment, GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, &value);
1633     switch (type) {
1634     case GraphicsContext3D::RENDERBUFFER:
1635         return WebGLGetInfo(PassRefPtr<WebGLRenderbuffer>(findRenderbuffer(static_cast<Platform3DObject>(value))));
1636     case GraphicsContext3D::TEXTURE:
1637         return WebGLGetInfo(PassRefPtr<WebGLTexture>(findTexture(static_cast<Platform3DObject>(value))));
1638     default:
1639         // FIXME: raise exception?
1640         return WebGLGetInfo();
1641     }
1642 }
1643
1644 WebGLGetInfo WebGLRenderingContext::getParameter(unsigned long pname, ExceptionCode& ec)
1645 {
1646     UNUSED_PARAM(ec);
1647     if (isContextLost())
1648         return WebGLGetInfo();
1649     WebGLStateRestorer(this, false);
1650     switch (pname) {
1651     case GraphicsContext3D::ACTIVE_TEXTURE:
1652         return getUnsignedLongParameter(pname);
1653     case GraphicsContext3D::ALIASED_LINE_WIDTH_RANGE:
1654         return getWebGLFloatArrayParameter(pname);
1655     case GraphicsContext3D::ALIASED_POINT_SIZE_RANGE:
1656         return getWebGLFloatArrayParameter(pname);
1657     case GraphicsContext3D::ALPHA_BITS:
1658         return getLongParameter(pname);
1659     case GraphicsContext3D::ARRAY_BUFFER_BINDING:
1660         return WebGLGetInfo(PassRefPtr<WebGLBuffer>(m_boundArrayBuffer));
1661     case GraphicsContext3D::BLEND:
1662         return getBooleanParameter(pname);
1663     case GraphicsContext3D::BLEND_COLOR:
1664         return getWebGLFloatArrayParameter(pname);
1665     case GraphicsContext3D::BLEND_DST_ALPHA:
1666         return getUnsignedLongParameter(pname);
1667     case GraphicsContext3D::BLEND_DST_RGB:
1668         return getUnsignedLongParameter(pname);
1669     case GraphicsContext3D::BLEND_EQUATION_ALPHA:
1670         return getUnsignedLongParameter(pname);
1671     case GraphicsContext3D::BLEND_EQUATION_RGB:
1672         return getUnsignedLongParameter(pname);
1673     case GraphicsContext3D::BLEND_SRC_ALPHA:
1674         return getUnsignedLongParameter(pname);
1675     case GraphicsContext3D::BLEND_SRC_RGB:
1676         return getUnsignedLongParameter(pname);
1677     case GraphicsContext3D::BLUE_BITS:
1678         return getLongParameter(pname);
1679     case GraphicsContext3D::COLOR_CLEAR_VALUE:
1680         return getWebGLFloatArrayParameter(pname);
1681     case GraphicsContext3D::COLOR_WRITEMASK:
1682         return getBooleanArrayParameter(pname);
1683     case GraphicsContext3D::COMPRESSED_TEXTURE_FORMATS:
1684         // Defined as null in the spec
1685         return WebGLGetInfo();
1686     case GraphicsContext3D::CULL_FACE:
1687         return getBooleanParameter(pname);
1688     case GraphicsContext3D::CULL_FACE_MODE:
1689         return getUnsignedLongParameter(pname);
1690     case GraphicsContext3D::CURRENT_PROGRAM:
1691         return WebGLGetInfo(PassRefPtr<WebGLProgram>(m_currentProgram));
1692     case GraphicsContext3D::DEPTH_BITS:
1693         return getLongParameter(pname);
1694     case GraphicsContext3D::DEPTH_CLEAR_VALUE:
1695         return getFloatParameter(pname);
1696     case GraphicsContext3D::DEPTH_FUNC:
1697         return getUnsignedLongParameter(pname);
1698     case GraphicsContext3D::DEPTH_RANGE:
1699         return getWebGLFloatArrayParameter(pname);
1700     case GraphicsContext3D::DEPTH_TEST:
1701         return getBooleanParameter(pname);
1702     case GraphicsContext3D::DEPTH_WRITEMASK:
1703         return getBooleanParameter(pname);
1704     case GraphicsContext3D::DITHER:
1705         return getBooleanParameter(pname);
1706     case GraphicsContext3D::ELEMENT_ARRAY_BUFFER_BINDING:
1707         return WebGLGetInfo(PassRefPtr<WebGLBuffer>(m_boundElementArrayBuffer));
1708     case GraphicsContext3D::FRAMEBUFFER_BINDING:
1709         return WebGLGetInfo(PassRefPtr<WebGLFramebuffer>(m_framebufferBinding));
1710     case GraphicsContext3D::FRONT_FACE:
1711         return getUnsignedLongParameter(pname);
1712     case GraphicsContext3D::GENERATE_MIPMAP_HINT:
1713         return getUnsignedLongParameter(pname);
1714     case GraphicsContext3D::GREEN_BITS:
1715         return getLongParameter(pname);
1716     case GraphicsContext3D::LINE_WIDTH:
1717         return getFloatParameter(pname);
1718     case GraphicsContext3D::MAX_COMBINED_TEXTURE_IMAGE_UNITS:
1719         return getLongParameter(pname);
1720     case GraphicsContext3D::MAX_CUBE_MAP_TEXTURE_SIZE:
1721         return getLongParameter(pname);
1722     case GraphicsContext3D::MAX_FRAGMENT_UNIFORM_VECTORS:
1723         return getLongParameter(pname);
1724     case GraphicsContext3D::MAX_RENDERBUFFER_SIZE:
1725         return getLongParameter(pname);
1726     case GraphicsContext3D::MAX_TEXTURE_IMAGE_UNITS:
1727         return getLongParameter(pname);
1728     case GraphicsContext3D::MAX_TEXTURE_SIZE:
1729         return getLongParameter(pname);
1730     case GraphicsContext3D::MAX_VARYING_VECTORS:
1731         return getLongParameter(pname);
1732     case GraphicsContext3D::MAX_VERTEX_ATTRIBS:
1733         return getLongParameter(pname);
1734     case GraphicsContext3D::MAX_VERTEX_TEXTURE_IMAGE_UNITS:
1735         return getLongParameter(pname);
1736     case GraphicsContext3D::MAX_VERTEX_UNIFORM_VECTORS:
1737         return getLongParameter(pname);
1738     case GraphicsContext3D::MAX_VIEWPORT_DIMS:
1739         return getWebGLIntArrayParameter(pname);
1740     case GraphicsContext3D::NUM_COMPRESSED_TEXTURE_FORMATS:
1741         // WebGL 1.0 specifies that there are no compressed texture formats.
1742         return WebGLGetInfo(static_cast<long>(0));
1743     case GraphicsContext3D::NUM_SHADER_BINARY_FORMATS:
1744         // FIXME: should we always return 0 for this?
1745         return getLongParameter(pname);
1746     case GraphicsContext3D::PACK_ALIGNMENT:
1747         return getLongParameter(pname);
1748     case GraphicsContext3D::POLYGON_OFFSET_FACTOR:
1749         return getFloatParameter(pname);
1750     case GraphicsContext3D::POLYGON_OFFSET_FILL:
1751         return getBooleanParameter(pname);
1752     case GraphicsContext3D::POLYGON_OFFSET_UNITS:
1753         return getFloatParameter(pname);
1754     case GraphicsContext3D::RED_BITS:
1755         return getLongParameter(pname);
1756     case GraphicsContext3D::RENDERBUFFER_BINDING:
1757         return WebGLGetInfo(PassRefPtr<WebGLRenderbuffer>(m_renderbufferBinding));
1758     case GraphicsContext3D::RENDERER:
1759         return WebGLGetInfo(m_context->getString(GraphicsContext3D::RENDERER));
1760     case GraphicsContext3D::SAMPLE_BUFFERS:
1761         return getLongParameter(pname);
1762     case GraphicsContext3D::SAMPLE_COVERAGE_INVERT:
1763         return getBooleanParameter(pname);
1764     case GraphicsContext3D::SAMPLE_COVERAGE_VALUE:
1765         return getFloatParameter(pname);
1766     case GraphicsContext3D::SAMPLES:
1767         return getLongParameter(pname);
1768     case GraphicsContext3D::SCISSOR_BOX:
1769         return getWebGLIntArrayParameter(pname);
1770     case GraphicsContext3D::SCISSOR_TEST:
1771         return getBooleanParameter(pname);
1772     case GraphicsContext3D::SHADING_LANGUAGE_VERSION:
1773         return WebGLGetInfo("WebGL GLSL ES 1.0 (" + m_context->getString(GraphicsContext3D::SHADING_LANGUAGE_VERSION) + ")");
1774     case GraphicsContext3D::STENCIL_BACK_FAIL:
1775         return getUnsignedLongParameter(pname);
1776     case GraphicsContext3D::STENCIL_BACK_FUNC:
1777         return getUnsignedLongParameter(pname);
1778     case GraphicsContext3D::STENCIL_BACK_PASS_DEPTH_FAIL:
1779         return getUnsignedLongParameter(pname);
1780     case GraphicsContext3D::STENCIL_BACK_PASS_DEPTH_PASS:
1781         return getUnsignedLongParameter(pname);
1782     case GraphicsContext3D::STENCIL_BACK_REF:
1783         return getLongParameter(pname);
1784     case GraphicsContext3D::STENCIL_BACK_VALUE_MASK:
1785         return getUnsignedLongParameter(pname);
1786     case GraphicsContext3D::STENCIL_BACK_WRITEMASK:
1787         return getUnsignedLongParameter(pname);
1788     case GraphicsContext3D::STENCIL_BITS:
1789         return getLongParameter(pname);
1790     case GraphicsContext3D::STENCIL_CLEAR_VALUE:
1791         return getLongParameter(pname);
1792     case GraphicsContext3D::STENCIL_FAIL:
1793         return getUnsignedLongParameter(pname);
1794     case GraphicsContext3D::STENCIL_FUNC:
1795         return getUnsignedLongParameter(pname);
1796     case GraphicsContext3D::STENCIL_PASS_DEPTH_FAIL:
1797         return getUnsignedLongParameter(pname);
1798     case GraphicsContext3D::STENCIL_PASS_DEPTH_PASS:
1799         return getUnsignedLongParameter(pname);
1800     case GraphicsContext3D::STENCIL_REF:
1801         return getLongParameter(pname);
1802     case GraphicsContext3D::STENCIL_TEST:
1803         return getBooleanParameter(pname);
1804     case GraphicsContext3D::STENCIL_VALUE_MASK:
1805         return getUnsignedLongParameter(pname);
1806     case GraphicsContext3D::STENCIL_WRITEMASK:
1807         return getUnsignedLongParameter(pname);
1808     case GraphicsContext3D::SUBPIXEL_BITS:
1809         return getLongParameter(pname);
1810     case GraphicsContext3D::TEXTURE_BINDING_2D:
1811         return WebGLGetInfo(PassRefPtr<WebGLTexture>(m_textureUnits[m_activeTextureUnit].m_texture2DBinding));
1812     case GraphicsContext3D::TEXTURE_BINDING_CUBE_MAP:
1813         return WebGLGetInfo(PassRefPtr<WebGLTexture>(m_textureUnits[m_activeTextureUnit].m_textureCubeMapBinding));
1814     case GraphicsContext3D::UNPACK_ALIGNMENT:
1815         // FIXME: should this be "long" in the spec?
1816         return getIntParameter(pname);
1817     case GraphicsContext3D::UNPACK_FLIP_Y_WEBGL:
1818         return WebGLGetInfo(m_unpackFlipY);
1819     case GraphicsContext3D::UNPACK_PREMULTIPLY_ALPHA_WEBGL:
1820         return WebGLGetInfo(m_unpackPremultiplyAlpha);
1821     case GraphicsContext3D::UNPACK_COLORSPACE_CONVERSION_WEBGL:
1822         return WebGLGetInfo(m_unpackColorspaceConversion);
1823     case GraphicsContext3D::VENDOR:
1824         return WebGLGetInfo("Webkit (" + m_context->getString(GraphicsContext3D::VENDOR) + ")");
1825     case GraphicsContext3D::VERSION:
1826         return WebGLGetInfo("WebGL 1.0 (" + m_context->getString(GraphicsContext3D::VERSION) + ")");
1827     case GraphicsContext3D::VIEWPORT:
1828         return getWebGLIntArrayParameter(pname);
1829     default:
1830         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
1831         return WebGLGetInfo();
1832     }
1833 }
1834
1835 WebGLGetInfo WebGLRenderingContext::getProgramParameter(WebGLProgram* program, unsigned long pname, ExceptionCode& ec)
1836 {
1837     UNUSED_PARAM(ec);
1838     if (isContextLost() || !validateWebGLObject(program))
1839         return WebGLGetInfo();
1840
1841     WebGLStateRestorer(this, false);
1842     int value = 0;
1843     switch (pname) {
1844     case GraphicsContext3D::DELETE_STATUS:
1845         return WebGLGetInfo(program->isDeleted());
1846     case GraphicsContext3D::VALIDATE_STATUS:
1847         m_context->getProgramiv(objectOrZero(program), pname, &value);
1848         return WebGLGetInfo(static_cast<bool>(value));
1849     case GraphicsContext3D::LINK_STATUS:
1850         return WebGLGetInfo(program->getLinkStatus());
1851     case GraphicsContext3D::INFO_LOG_LENGTH:
1852     case GraphicsContext3D::ATTACHED_SHADERS:
1853     case GraphicsContext3D::ACTIVE_ATTRIBUTES:
1854     case GraphicsContext3D::ACTIVE_ATTRIBUTE_MAX_LENGTH:
1855     case GraphicsContext3D::ACTIVE_UNIFORMS:
1856     case GraphicsContext3D::ACTIVE_UNIFORM_MAX_LENGTH:
1857         m_context->getProgramiv(objectOrZero(program), pname, &value);
1858         return WebGLGetInfo(static_cast<long>(value));
1859     default:
1860         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
1861         return WebGLGetInfo();
1862     }
1863 }
1864
1865 String WebGLRenderingContext::getProgramInfoLog(WebGLProgram* program, ExceptionCode& ec)
1866 {
1867     UNUSED_PARAM(ec);
1868     if (isContextLost())
1869         return String();
1870     if (!validateWebGLObject(program))
1871         return "";
1872     WebGLStateRestorer(this, false);
1873     return m_context->getProgramInfoLog(objectOrZero(program));
1874 }
1875
1876 WebGLGetInfo WebGLRenderingContext::getRenderbufferParameter(unsigned long target, unsigned long pname, ExceptionCode& ec)
1877 {
1878     UNUSED_PARAM(ec);
1879     if (isContextLost())
1880         return WebGLGetInfo();
1881     if (target != GraphicsContext3D::RENDERBUFFER) {
1882         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
1883         return WebGLGetInfo();
1884     }
1885     if (!m_renderbufferBinding || !m_renderbufferBinding->object()) {
1886         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
1887         return WebGLGetInfo();
1888     }
1889
1890     if (m_renderbufferBinding->getInternalFormat() == GraphicsContext3D::DEPTH_STENCIL
1891         && !m_renderbufferBinding->isValid()) {
1892         ASSERT(!isDepthStencilSupported());
1893         long value = 0;
1894         switch (pname) {
1895         case GraphicsContext3D::RENDERBUFFER_WIDTH:
1896             value = static_cast<long>(m_renderbufferBinding->getWidth());
1897             break;
1898         case GraphicsContext3D::RENDERBUFFER_HEIGHT:
1899             value = static_cast<long>(m_renderbufferBinding->getHeight());
1900             break;
1901         case GraphicsContext3D::RENDERBUFFER_RED_SIZE:
1902         case GraphicsContext3D::RENDERBUFFER_GREEN_SIZE:
1903         case GraphicsContext3D::RENDERBUFFER_BLUE_SIZE:
1904         case GraphicsContext3D::RENDERBUFFER_ALPHA_SIZE:
1905             value = 0;
1906             break;
1907         case GraphicsContext3D::RENDERBUFFER_DEPTH_SIZE:
1908             value = 24;
1909             break;
1910         case GraphicsContext3D::RENDERBUFFER_STENCIL_SIZE:
1911             value = 8;
1912             break;
1913         case GraphicsContext3D::RENDERBUFFER_INTERNAL_FORMAT:
1914             return WebGLGetInfo(m_renderbufferBinding->getInternalFormat());
1915         default:
1916             m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
1917             return WebGLGetInfo();
1918         }
1919         return WebGLGetInfo(value);
1920     }
1921
1922     WebGLStateRestorer(this, false);
1923     int value = 0;
1924     switch (pname) {
1925     case GraphicsContext3D::RENDERBUFFER_WIDTH:
1926     case GraphicsContext3D::RENDERBUFFER_HEIGHT:
1927     case GraphicsContext3D::RENDERBUFFER_RED_SIZE:
1928     case GraphicsContext3D::RENDERBUFFER_GREEN_SIZE:
1929     case GraphicsContext3D::RENDERBUFFER_BLUE_SIZE:
1930     case GraphicsContext3D::RENDERBUFFER_ALPHA_SIZE:
1931     case GraphicsContext3D::RENDERBUFFER_DEPTH_SIZE:
1932     case GraphicsContext3D::RENDERBUFFER_STENCIL_SIZE:
1933         m_context->getRenderbufferParameteriv(target, pname, &value);
1934         return WebGLGetInfo(static_cast<long>(value));
1935     case GraphicsContext3D::RENDERBUFFER_INTERNAL_FORMAT:
1936         return WebGLGetInfo(m_renderbufferBinding->getInternalFormat());
1937     default:
1938         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
1939         return WebGLGetInfo();
1940     }
1941 }
1942
1943 WebGLGetInfo WebGLRenderingContext::getShaderParameter(WebGLShader* shader, unsigned long pname, ExceptionCode& ec)
1944 {
1945     UNUSED_PARAM(ec);
1946     if (isContextLost() || !validateWebGLObject(shader))
1947         return WebGLGetInfo();
1948     WebGLStateRestorer(this, false);
1949     int value = 0;
1950     switch (pname) {
1951     case GraphicsContext3D::DELETE_STATUS:
1952         return WebGLGetInfo(shader->isDeleted());
1953     case GraphicsContext3D::COMPILE_STATUS:
1954         m_context->getShaderiv(objectOrZero(shader), pname, &value);
1955         return WebGLGetInfo(static_cast<bool>(value));
1956     case GraphicsContext3D::SHADER_TYPE:
1957         m_context->getShaderiv(objectOrZero(shader), pname, &value);
1958         return WebGLGetInfo(static_cast<unsigned long>(value));
1959     case GraphicsContext3D::INFO_LOG_LENGTH:
1960     case GraphicsContext3D::SHADER_SOURCE_LENGTH:
1961         m_context->getShaderiv(objectOrZero(shader), pname, &value);
1962         return WebGLGetInfo(static_cast<long>(value));
1963     default:
1964         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
1965         return WebGLGetInfo();
1966     }
1967 }
1968
1969 String WebGLRenderingContext::getShaderInfoLog(WebGLShader* shader, ExceptionCode& ec)
1970 {
1971     UNUSED_PARAM(ec);
1972     if (isContextLost())
1973         return String();
1974     if (!validateWebGLObject(shader))
1975         return "";
1976     WebGLStateRestorer(this, false);
1977     return m_context->getShaderInfoLog(objectOrZero(shader));
1978 }
1979
1980 String WebGLRenderingContext::getShaderSource(WebGLShader* shader, ExceptionCode& ec)
1981 {
1982     UNUSED_PARAM(ec);
1983     if (isContextLost())
1984         return String();
1985     if (!validateWebGLObject(shader))
1986         return "";
1987     WebGLStateRestorer(this, false);
1988     return m_context->getShaderSource(objectOrZero(shader));
1989 }
1990
1991 Vector<String> WebGLRenderingContext::getSupportedExtensions()
1992 {
1993     Vector<String> result;
1994     if (m_context->getExtensions()->supports("GL_OES_texture_float"))
1995         result.append("OES_texture_float");
1996     result.append("WEBKIT_lose_context");
1997     return result;
1998 }
1999
2000 WebGLGetInfo WebGLRenderingContext::getTexParameter(unsigned long target, unsigned long pname, ExceptionCode& ec)
2001 {
2002     UNUSED_PARAM(ec);
2003     if (isContextLost())
2004         return WebGLGetInfo();
2005     WebGLTexture* tex = validateTextureBinding(target, false);
2006     if (!tex)
2007         return WebGLGetInfo();
2008     WebGLStateRestorer(this, false);
2009     int value = 0;
2010     switch (pname) {
2011     case GraphicsContext3D::TEXTURE_MAG_FILTER:
2012     case GraphicsContext3D::TEXTURE_MIN_FILTER:
2013     case GraphicsContext3D::TEXTURE_WRAP_S:
2014     case GraphicsContext3D::TEXTURE_WRAP_T:
2015         m_context->getTexParameteriv(target, pname, &value);
2016         return WebGLGetInfo(static_cast<unsigned long>(value));
2017     default:
2018         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
2019         return WebGLGetInfo();
2020     }
2021 }
2022
2023 WebGLGetInfo WebGLRenderingContext::getUniform(WebGLProgram* program, const WebGLUniformLocation* uniformLocation, ExceptionCode& ec)
2024 {
2025     UNUSED_PARAM(ec);
2026     if (isContextLost() || !validateWebGLObject(program))
2027         return WebGLGetInfo();
2028     if (!uniformLocation || uniformLocation->program() != program) {
2029         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
2030         return WebGLGetInfo();
2031     }
2032     long location = uniformLocation->location();
2033     
2034     WebGLStateRestorer(this, false);
2035     // FIXME: make this more efficient using WebGLUniformLocation and caching types in it
2036     int activeUniforms = 0;
2037     m_context->getProgramiv(objectOrZero(program), GraphicsContext3D::ACTIVE_UNIFORMS, &activeUniforms);
2038     for (int i = 0; i < activeUniforms; i++) {
2039         ActiveInfo info;
2040         if (!m_context->getActiveUniform(objectOrZero(program), i, info))
2041             return WebGLGetInfo();
2042         // Strip "[0]" from the name if it's an array.
2043         if (info.size > 1)
2044             info.name = info.name.left(info.name.length() - 3);
2045         // If it's an array, we need to iterate through each element, appending "[index]" to the name.
2046         for (int index = 0; index < info.size; ++index) {
2047             String name = info.name;
2048             if (info.size > 1 && index >= 1) {
2049                 name.append('[');
2050                 name.append(String::number(index));
2051                 name.append(']');
2052             }
2053             // Now need to look this up by name again to find its location
2054             long loc = m_context->getUniformLocation(objectOrZero(program), name);
2055             if (loc == location) {
2056                 // Found it. Use the type in the ActiveInfo to determine the return type.
2057                 GraphicsContext3D::WebGLEnumType baseType;
2058                 unsigned length;
2059                 switch (info.type) {
2060                 case GraphicsContext3D::BOOL:
2061                     baseType = GraphicsContext3D::BOOL;
2062                     length = 1;
2063                     break;
2064                 case GraphicsContext3D::BOOL_VEC2:
2065                     baseType = GraphicsContext3D::BOOL;
2066                     length = 2;
2067                     break;
2068                 case GraphicsContext3D::BOOL_VEC3:
2069                     baseType = GraphicsContext3D::BOOL;
2070                     length = 3;
2071                     break;
2072                 case GraphicsContext3D::BOOL_VEC4:
2073                     baseType = GraphicsContext3D::BOOL;
2074                     length = 4;
2075                     break;
2076                 case GraphicsContext3D::INT:
2077                     baseType = GraphicsContext3D::INT;
2078                     length = 1;
2079                     break;
2080                 case GraphicsContext3D::INT_VEC2:
2081                     baseType = GraphicsContext3D::INT;
2082                     length = 2;
2083                     break;
2084                 case GraphicsContext3D::INT_VEC3:
2085                     baseType = GraphicsContext3D::INT;
2086                     length = 3;
2087                     break;
2088                 case GraphicsContext3D::INT_VEC4:
2089                     baseType = GraphicsContext3D::INT;
2090                     length = 4;
2091                     break;
2092                 case GraphicsContext3D::FLOAT:
2093                     baseType = GraphicsContext3D::FLOAT;
2094                     length = 1;
2095                     break;
2096                 case GraphicsContext3D::FLOAT_VEC2:
2097                     baseType = GraphicsContext3D::FLOAT;
2098                     length = 2;
2099                     break;
2100                 case GraphicsContext3D::FLOAT_VEC3:
2101                     baseType = GraphicsContext3D::FLOAT;
2102                     length = 3;
2103                     break;
2104                 case GraphicsContext3D::FLOAT_VEC4:
2105                     baseType = GraphicsContext3D::FLOAT;
2106                     length = 4;
2107                     break;
2108                 case GraphicsContext3D::FLOAT_MAT2:
2109                     baseType = GraphicsContext3D::FLOAT;
2110                     length = 4;
2111                     break;
2112                 case GraphicsContext3D::FLOAT_MAT3:
2113                     baseType = GraphicsContext3D::FLOAT;
2114                     length = 9;
2115                     break;
2116                 case GraphicsContext3D::FLOAT_MAT4:
2117                     baseType = GraphicsContext3D::FLOAT;
2118                     length = 16;
2119                     break;
2120                 default:
2121                     // Can't handle this type
2122                     // FIXME: what to do about samplers?
2123                     m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
2124                     return WebGLGetInfo();
2125                 }
2126                 switch (baseType) {
2127                 case GraphicsContext3D::FLOAT: {
2128                     float value[16] = {0};
2129                     m_context->getUniformfv(objectOrZero(program), location, value);
2130                     if (length == 1)
2131                         return WebGLGetInfo(value[0]);
2132                     return WebGLGetInfo(Float32Array::create(value, length));
2133                 }
2134                 case GraphicsContext3D::INT: {
2135                     int value[4] = {0};
2136                     m_context->getUniformiv(objectOrZero(program), location, value);
2137                     if (length == 1)
2138                         return WebGLGetInfo(static_cast<long>(value[0]));
2139                     return WebGLGetInfo(Int32Array::create(value, length));
2140                 }
2141                 case GraphicsContext3D::BOOL: {
2142                     int value[4] = {0};
2143                     m_context->getUniformiv(objectOrZero(program), location, value);
2144                     if (length > 1) {
2145                         bool boolValue[16] = {0};
2146                         for (unsigned j = 0; j < length; j++)
2147                             boolValue[j] = static_cast<bool>(value[j]);
2148                         return WebGLGetInfo(boolValue, length);
2149                     }
2150                     return WebGLGetInfo(static_cast<bool>(value[0]));
2151                 }
2152                 default:
2153                     notImplemented();
2154                 }
2155             }
2156         }
2157     }
2158     // If we get here, something went wrong in our unfortunately complex logic above
2159     m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
2160     return WebGLGetInfo();
2161 }
2162
2163 PassRefPtr<WebGLUniformLocation> WebGLRenderingContext::getUniformLocation(WebGLProgram* program, const String& name, ExceptionCode& ec)
2164 {
2165     UNUSED_PARAM(ec);
2166     if (isContextLost() || !validateWebGLObject(program))
2167         return 0;
2168     if (!validateString(name))
2169         return 0;
2170     WebGLStateRestorer(this, false);
2171     long uniformLocation = m_context->getUniformLocation(objectOrZero(program), name);
2172     if (uniformLocation == -1)
2173         return 0;
2174     return WebGLUniformLocation::create(program, uniformLocation);
2175 }
2176
2177 WebGLGetInfo WebGLRenderingContext::getVertexAttrib(unsigned long index, unsigned long pname, ExceptionCode& ec)
2178 {
2179     UNUSED_PARAM(ec);
2180     if (isContextLost())
2181         return WebGLGetInfo();
2182     WebGLStateRestorer(this, false);
2183     if (index >= m_maxVertexAttribs) {
2184         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
2185         return WebGLGetInfo();
2186     }
2187     switch (pname) {
2188     case GraphicsContext3D::VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
2189         if ((!isGLES2Compliant() && !index && m_vertexAttribState[0].bufferBinding == m_vertexAttrib0Buffer)
2190             || index >= m_vertexAttribState.size()
2191             || !m_vertexAttribState[index].bufferBinding
2192             || !m_vertexAttribState[index].bufferBinding->object())
2193             return WebGLGetInfo();
2194         return WebGLGetInfo(PassRefPtr<WebGLBuffer>(m_vertexAttribState[index].bufferBinding));
2195     case GraphicsContext3D::VERTEX_ATTRIB_ARRAY_ENABLED:
2196         if (index >= m_vertexAttribState.size())
2197             return WebGLGetInfo(false);
2198         return WebGLGetInfo(m_vertexAttribState[index].enabled);
2199     case GraphicsContext3D::VERTEX_ATTRIB_ARRAY_NORMALIZED:
2200         if (index >= m_vertexAttribState.size())
2201             return WebGLGetInfo(false);
2202         return WebGLGetInfo(m_vertexAttribState[index].normalized);
2203     case GraphicsContext3D::VERTEX_ATTRIB_ARRAY_SIZE:
2204         if (index >= m_vertexAttribState.size())
2205             return WebGLGetInfo(static_cast<long>(4));
2206         return WebGLGetInfo(m_vertexAttribState[index].size);
2207     case GraphicsContext3D::VERTEX_ATTRIB_ARRAY_STRIDE:
2208         if (index >= m_vertexAttribState.size())
2209             return WebGLGetInfo(static_cast<long>(0));
2210         return WebGLGetInfo(m_vertexAttribState[index].originalStride);
2211     case GraphicsContext3D::VERTEX_ATTRIB_ARRAY_TYPE:
2212         if (index >= m_vertexAttribState.size())
2213             return WebGLGetInfo(static_cast<unsigned long>(GraphicsContext3D::FLOAT));
2214         return WebGLGetInfo(m_vertexAttribState[index].type);
2215     case GraphicsContext3D::CURRENT_VERTEX_ATTRIB:
2216         if (index >= m_vertexAttribState.size()) {
2217             float value[4] = { 0.0f, 0.0f, 0.0f, 1.0f };
2218             return WebGLGetInfo(Float32Array::create(value, 4));
2219         }
2220         return WebGLGetInfo(Float32Array::create(m_vertexAttribState[index].value, 4));
2221     default:
2222         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
2223         return WebGLGetInfo();
2224     }
2225 }
2226
2227 long WebGLRenderingContext::getVertexAttribOffset(unsigned long index, unsigned long pname)
2228 {
2229     if (isContextLost())
2230         return 0;
2231     long result = m_context->getVertexAttribOffset(index, pname);
2232     cleanupAfterGraphicsCall(false);
2233     return result;
2234 }
2235
2236 void WebGLRenderingContext::hint(unsigned long target, unsigned long mode)
2237 {
2238     if (isContextLost())
2239         return;
2240     if (target != GraphicsContext3D::GENERATE_MIPMAP_HINT) {
2241         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
2242         return;
2243     }
2244     m_context->hint(target, mode);
2245     cleanupAfterGraphicsCall(false);
2246 }
2247
2248 bool WebGLRenderingContext::isBuffer(WebGLBuffer* buffer)
2249 {
2250     if (!buffer || isContextLost())
2251         return false;
2252
2253     if (!buffer->hasEverBeenBound())
2254         return false;
2255
2256     return m_context->isBuffer(buffer->object());
2257 }
2258
2259 bool WebGLRenderingContext::isContextLost()
2260 {
2261     if (m_restoreTimer.isActive())
2262         return true;
2263
2264     bool newContextLost = m_context->getExtensions()->getGraphicsResetStatusARB() != GraphicsContext3D::NO_ERROR;
2265
2266     if (newContextLost != m_contextLost)
2267         m_restoreTimer.startOneShot(secondsBetweenRestoreAttempts);
2268
2269     return m_contextLost;
2270 }
2271
2272 bool WebGLRenderingContext::isEnabled(unsigned long cap)
2273 {
2274     if (!validateCapability(cap) || isContextLost())
2275         return false;
2276     return m_context->isEnabled(cap);
2277 }
2278
2279 bool WebGLRenderingContext::isFramebuffer(WebGLFramebuffer* framebuffer)
2280 {
2281     if (!framebuffer || isContextLost())
2282         return false;
2283
2284     if (!framebuffer->hasEverBeenBound())
2285         return false;
2286
2287     return m_context->isFramebuffer(framebuffer->object());
2288 }
2289
2290 bool WebGLRenderingContext::isProgram(WebGLProgram* program)
2291 {
2292     if (!program || isContextLost())
2293         return false;
2294
2295     return m_context->isProgram(program->object());
2296 }
2297
2298 bool WebGLRenderingContext::isRenderbuffer(WebGLRenderbuffer* renderbuffer)
2299 {
2300     if (!renderbuffer || isContextLost())
2301         return false;
2302
2303     if (!renderbuffer->hasEverBeenBound())
2304         return false;
2305
2306     return m_context->isRenderbuffer(renderbuffer->object());
2307 }
2308
2309 bool WebGLRenderingContext::isShader(WebGLShader* shader)
2310 {
2311     if (!shader || isContextLost())
2312         return false;
2313
2314     return m_context->isShader(shader->object());
2315 }
2316
2317 bool WebGLRenderingContext::isTexture(WebGLTexture* texture)
2318 {
2319     if (!texture || isContextLost())
2320         return false;
2321
2322     if (!texture->hasEverBeenBound())
2323         return false;
2324
2325     return m_context->isTexture(texture->object());
2326 }
2327
2328 void WebGLRenderingContext::lineWidth(float width)
2329 {
2330     if (isContextLost())
2331         return;
2332     m_context->lineWidth((float) width);
2333     cleanupAfterGraphicsCall(false);
2334 }
2335
2336 void WebGLRenderingContext::linkProgram(WebGLProgram* program, ExceptionCode& ec)
2337 {
2338     UNUSED_PARAM(ec);
2339     if (isContextLost() || !validateWebGLObject(program))
2340         return;
2341     if (!isGLES2Compliant()) {
2342         if (!program->getAttachedShader(GraphicsContext3D::VERTEX_SHADER) || !program->getAttachedShader(GraphicsContext3D::FRAGMENT_SHADER)) {
2343             program->setLinkStatus(false);
2344             return;
2345         }
2346     }
2347
2348     m_context->linkProgram(objectOrZero(program));
2349     program->increaseLinkCount();
2350     // cache link status
2351     int value = 0;
2352     m_context->getProgramiv(objectOrZero(program), GraphicsContext3D::LINK_STATUS, &value);
2353     program->setLinkStatus(static_cast<bool>(value));
2354     // Need to cache link status before caching active attribute locations.
2355     program->cacheActiveAttribLocations();
2356     cleanupAfterGraphicsCall(false);
2357 }
2358
2359 void WebGLRenderingContext::pixelStorei(unsigned long pname, long param)
2360 {
2361     if (isContextLost())
2362         return;
2363     switch (pname) {
2364     case GraphicsContext3D::UNPACK_FLIP_Y_WEBGL:
2365         m_unpackFlipY = param;
2366         break;
2367     case GraphicsContext3D::UNPACK_PREMULTIPLY_ALPHA_WEBGL:
2368         m_unpackPremultiplyAlpha = param;
2369         break;
2370     case GraphicsContext3D::UNPACK_COLORSPACE_CONVERSION_WEBGL:
2371         if (param == GraphicsContext3D::BROWSER_DEFAULT_WEBGL || param == GraphicsContext3D::NONE)
2372             m_unpackColorspaceConversion = static_cast<unsigned long>(param);
2373         else {
2374             m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
2375             return;
2376         }
2377         break;
2378     case GraphicsContext3D::PACK_ALIGNMENT:
2379     case GraphicsContext3D::UNPACK_ALIGNMENT:
2380         if (param == 1 || param == 2 || param == 4 || param == 8) {
2381             if (pname == GraphicsContext3D::PACK_ALIGNMENT)
2382                 m_packAlignment = static_cast<int>(param);
2383             else // GraphicsContext3D::UNPACK_ALIGNMENT:
2384                 m_unpackAlignment = static_cast<int>(param);
2385             m_context->pixelStorei(pname, param);
2386             cleanupAfterGraphicsCall(false);
2387         } else {
2388             m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
2389             return;
2390         }
2391         break;
2392     default:
2393         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
2394         return;
2395     }
2396 }
2397
2398 void WebGLRenderingContext::polygonOffset(float factor, float units)
2399 {
2400     if (isContextLost())
2401         return;
2402     m_context->polygonOffset((float) factor, (float) units);
2403     cleanupAfterGraphicsCall(false);
2404 }
2405
2406 void WebGLRenderingContext::readPixels(long x, long y, long width, long height, unsigned long format, unsigned long type, ArrayBufferView* pixels, ExceptionCode& ec)
2407 {
2408     if (isContextLost())
2409         return;
2410     if (!canvas()->originClean()) {
2411         ec = SECURITY_ERR;
2412         return;
2413     }
2414     // Validate input parameters.
2415     unsigned int componentsPerPixel, bytesPerComponent;
2416     if (!m_context->computeFormatAndTypeParameters(format, type, &componentsPerPixel, &bytesPerComponent)) {
2417         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
2418         return;
2419     }
2420     if (!pixels) {
2421         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
2422         return;
2423     }
2424     if (width < 0 || height < 0) {
2425         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
2426         return;
2427     }
2428     if (format != GraphicsContext3D::RGBA && type != GraphicsContext3D::UNSIGNED_BYTE) {
2429         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
2430         return;
2431     }
2432     if (format != GraphicsContext3D::RGBA || type != GraphicsContext3D::UNSIGNED_BYTE) {
2433         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
2434         return;
2435     }
2436     // Validate array type against pixel type.
2437     if ((type == GraphicsContext3D::UNSIGNED_BYTE && !pixels->isUnsignedByteArray())
2438         || (type != GraphicsContext3D::UNSIGNED_BYTE && !pixels->isUnsignedShortArray())) {
2439         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
2440         return;
2441     }
2442     if (m_framebufferBinding && !m_framebufferBinding->onAccess(!isResourceSafe())) {
2443         m_context->synthesizeGLError(GraphicsContext3D::INVALID_FRAMEBUFFER_OPERATION);
2444         return;
2445     }
2446     // Calculate array size, taking into consideration of PACK_ALIGNMENT.
2447     unsigned long bytesPerRow = componentsPerPixel * bytesPerComponent * width;
2448     unsigned long padding = 0;
2449     unsigned long residualBytes = bytesPerRow % m_packAlignment;
2450     if (residualBytes) {
2451         padding = m_packAlignment - residualBytes;
2452         bytesPerRow += padding;
2453     }
2454     // The last row needs no padding.
2455     unsigned long totalBytes = bytesPerRow * height - padding;
2456     unsigned long num = totalBytes / bytesPerComponent;
2457     if (pixels->byteLength() / bytesPerComponent < num) {
2458         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
2459         return;
2460     }
2461     void* data = pixels->baseAddress();
2462     m_context->readPixels(x, y, width, height, format, type, data);
2463 #if PLATFORM(CG)
2464     // FIXME: remove this section when GL driver bug on Mac is fixed, i.e.,
2465     // when alpha is off, readPixels should set alpha to 255 instead of 0.
2466     if ((format == GraphicsContext3D::ALPHA || format == GraphicsContext3D::RGBA) && !m_context->getContextAttributes().alpha) {
2467         if (type == GraphicsContext3D::UNSIGNED_BYTE) {
2468             unsigned char* pixels = reinterpret_cast<unsigned char*>(data);
2469             for (long iy = 0; iy < height; ++iy) {
2470                 for (long ix = 0; ix < width; ++ix) {
2471                     pixels[componentsPerPixel - 1] = 255;
2472                     pixels += componentsPerPixel;
2473                 }
2474                 pixels += padding;
2475             }
2476         }
2477         // FIXME: check whether we need to do the same with UNSIGNED_SHORT.
2478     }
2479 #endif
2480     cleanupAfterGraphicsCall(false);
2481 }
2482
2483 void WebGLRenderingContext::releaseShaderCompiler()
2484 {
2485     if (isContextLost())
2486         return;
2487     m_context->releaseShaderCompiler();
2488     cleanupAfterGraphicsCall(false);
2489 }
2490
2491 void WebGLRenderingContext::renderbufferStorage(unsigned long target, unsigned long internalformat, long width, long height)
2492 {
2493     if (isContextLost())
2494         return;
2495     if (target != GraphicsContext3D::RENDERBUFFER) {
2496         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
2497         return;
2498     }
2499     if (!m_renderbufferBinding || !m_renderbufferBinding->object()) {
2500         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
2501         return;
2502     }
2503     if (!validateSize(width, height))
2504         return;
2505     switch (internalformat) {
2506     case GraphicsContext3D::DEPTH_COMPONENT16:
2507     case GraphicsContext3D::RGBA4:
2508     case GraphicsContext3D::RGB5_A1:
2509     case GraphicsContext3D::RGB565:
2510     case GraphicsContext3D::STENCIL_INDEX8:
2511         m_context->renderbufferStorage(target, internalformat, width, height);
2512         m_renderbufferBinding->setInternalFormat(internalformat);
2513         m_renderbufferBinding->setIsValid(true);
2514         m_renderbufferBinding->setSize(width, height);
2515         cleanupAfterGraphicsCall(false);
2516         break;
2517     case GraphicsContext3D::DEPTH_STENCIL:
2518         if (isDepthStencilSupported()) {
2519             m_context->renderbufferStorage(target, Extensions3D::DEPTH24_STENCIL8, width, height);
2520             cleanupAfterGraphicsCall(false);
2521         }
2522         m_renderbufferBinding->setSize(width, height);
2523         m_renderbufferBinding->setIsValid(isDepthStencilSupported());
2524         m_renderbufferBinding->setInternalFormat(internalformat);
2525         break;
2526     default:
2527         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
2528     }
2529 }
2530
2531 void WebGLRenderingContext::sampleCoverage(float value, bool invert)
2532 {
2533     if (isContextLost())
2534         return;
2535     m_context->sampleCoverage((float) value, invert);
2536     cleanupAfterGraphicsCall(false);
2537 }
2538
2539 void WebGLRenderingContext::scissor(long x, long y, long width, long height)
2540 {
2541     if (isContextLost())
2542         return;
2543     if (!validateSize(width, height))
2544         return;
2545     m_context->scissor(x, y, width, height);
2546     cleanupAfterGraphicsCall(false);
2547 }
2548
2549 void WebGLRenderingContext::shaderSource(WebGLShader* shader, const String& string, ExceptionCode& ec)
2550 {
2551     UNUSED_PARAM(ec);
2552     if (isContextLost() || !validateWebGLObject(shader))
2553         return;
2554     if (!validateString(string))
2555         return;
2556     m_context->shaderSource(objectOrZero(shader), string);
2557     cleanupAfterGraphicsCall(false);
2558 }
2559
2560 void WebGLRenderingContext::stencilFunc(unsigned long func, long ref, unsigned long mask)
2561 {
2562     if (isContextLost())
2563         return;
2564     if (!validateStencilFunc(func))
2565         return;
2566     m_stencilFuncRef = ref;
2567     m_stencilFuncRefBack = ref;
2568     m_stencilFuncMask = mask;
2569     m_stencilFuncMaskBack = mask;
2570     m_context->stencilFunc(func, ref, mask);
2571     cleanupAfterGraphicsCall(false);
2572 }
2573
2574 void WebGLRenderingContext::stencilFuncSeparate(unsigned long face, unsigned long func, long ref, unsigned long mask)
2575 {
2576     if (isContextLost())
2577         return;
2578     if (!validateStencilFunc(func))
2579         return;
2580     switch (face) {
2581     case GraphicsContext3D::FRONT_AND_BACK:
2582         m_stencilFuncRef = ref;
2583         m_stencilFuncRefBack = ref;
2584         m_stencilFuncMask = mask;
2585         m_stencilFuncMaskBack = mask;
2586         break;
2587     case GraphicsContext3D::FRONT:
2588         m_stencilFuncRef = ref;
2589         m_stencilFuncMask = mask;
2590         break;
2591     case GraphicsContext3D::BACK:
2592         m_stencilFuncRefBack = ref;
2593         m_stencilFuncMaskBack = mask;
2594         break;
2595     default:
2596         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
2597         return;
2598     }
2599     m_context->stencilFuncSeparate(face, func, ref, mask);
2600     cleanupAfterGraphicsCall(false);
2601 }
2602
2603 void WebGLRenderingContext::stencilMask(unsigned long mask)
2604 {
2605     if (isContextLost())
2606         return;
2607     m_stencilMask = mask;
2608     m_stencilMaskBack = mask;
2609     m_context->stencilMask(mask);
2610     cleanupAfterGraphicsCall(false);
2611 }
2612
2613 void WebGLRenderingContext::stencilMaskSeparate(unsigned long face, unsigned long mask)
2614 {
2615     if (isContextLost())
2616         return;
2617     switch (face) {
2618     case GraphicsContext3D::FRONT_AND_BACK:
2619         m_stencilMask = mask;
2620         m_stencilMaskBack = mask;
2621         break;
2622     case GraphicsContext3D::FRONT:
2623         m_stencilMask = mask;
2624         break;
2625     case GraphicsContext3D::BACK:
2626         m_stencilMaskBack = mask;
2627         break;
2628     default:
2629         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
2630         return;
2631     }
2632     m_context->stencilMaskSeparate(face, mask);
2633     cleanupAfterGraphicsCall(false);
2634 }
2635
2636 void WebGLRenderingContext::stencilOp(unsigned long fail, unsigned long zfail, unsigned long zpass)
2637 {
2638     if (isContextLost())
2639         return;
2640     m_context->stencilOp(fail, zfail, zpass);
2641     cleanupAfterGraphicsCall(false);
2642 }
2643
2644 void WebGLRenderingContext::stencilOpSeparate(unsigned long face, unsigned long fail, unsigned long zfail, unsigned long zpass)
2645 {
2646     if (isContextLost())
2647         return;
2648     m_context->stencilOpSeparate(face, fail, zfail, zpass);
2649     cleanupAfterGraphicsCall(false);
2650 }
2651
2652 void WebGLRenderingContext::texImage2DBase(unsigned target, unsigned level, unsigned internalformat,
2653                                            int width, int height, unsigned border,
2654                                            unsigned format, unsigned type, void* pixels, ExceptionCode& ec)
2655 {
2656     // FIXME: For now we ignore any errors returned
2657     ec = 0;
2658     if (!validateTexFuncParameters(target, level, internalformat, width, height, border, format, type))
2659         return;
2660     WebGLTexture* tex = validateTextureBinding(target, true);
2661     if (!tex)
2662         return;
2663     if (!isGLES2NPOTStrict()) {
2664         if (level && WebGLTexture::isNPOT(width, height)) {
2665             m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
2666             return;
2667         }
2668     }
2669     if (!pixels && !isResourceSafe()) {
2670         bool succeed = m_context->texImage2DResourceSafe(target, level, internalformat, width, height,
2671                                                          border, format, type);
2672         if (!succeed)
2673             return;
2674     } else {
2675         m_context->texImage2D(target, level, internalformat, width, height,
2676                               border, format, type, pixels);
2677     }
2678     tex->setLevelInfo(target, level, internalformat, width, height, type);
2679     cleanupAfterGraphicsCall(false);
2680 }
2681
2682 void WebGLRenderingContext::texImage2DImpl(unsigned target, unsigned level, unsigned internalformat,
2683                                            unsigned format, unsigned type, Image* image,
2684                                            bool flipY, bool premultiplyAlpha, ExceptionCode& ec)
2685 {
2686     ec = 0;
2687     Vector<uint8_t> data;
2688     if (!m_context->extractImageData(image, format, type, flipY, premultiplyAlpha, m_unpackColorspaceConversion == GraphicsContext3D::NONE, data)) {
2689         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
2690         return;
2691     }
2692     if (m_unpackAlignment != 1)
2693         m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, 1);
2694     texImage2DBase(target, level, internalformat, image->width(), image->height(), 0,
2695                    format, type, data.data(), ec);
2696     if (m_unpackAlignment != 1)
2697         m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, m_unpackAlignment);
2698 }
2699
2700 void WebGLRenderingContext::texImage2D(unsigned target, unsigned level, unsigned internalformat,
2701                                        int width, int height, unsigned border,
2702                                        unsigned format, unsigned type, ArrayBufferView* pixels, ExceptionCode& ec)
2703 {
2704     if (isContextLost() || !validateTexFuncData(width, height, format, type, pixels))
2705         return;
2706     void* data = pixels ? pixels->baseAddress() : 0;
2707     Vector<uint8_t> tempData;
2708     bool changeUnpackAlignment = false;
2709     if (data && (m_unpackFlipY || m_unpackPremultiplyAlpha)) {
2710         if (!m_context->extractTextureData(width, height, format, type,
2711                                            m_unpackAlignment,
2712                                            m_unpackFlipY, m_unpackPremultiplyAlpha,
2713                                            data,
2714                                            tempData))
2715             return;
2716         data = tempData.data();
2717         changeUnpackAlignment = true;
2718     }
2719     if (changeUnpackAlignment)
2720         m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, 1);
2721     texImage2DBase(target, level, internalformat, width, height, border,
2722                    format, type, data, ec);
2723     if (changeUnpackAlignment)
2724         m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, m_unpackAlignment);
2725 }
2726
2727 void WebGLRenderingContext::texImage2D(unsigned target, unsigned level, unsigned internalformat,
2728                                        unsigned format, unsigned type, ImageData* pixels, ExceptionCode& ec)
2729 {
2730     ec = 0;
2731     if (isContextLost())
2732         return;
2733     Vector<uint8_t> data;
2734     if (!m_context->extractImageData(pixels, format, type, m_unpackFlipY, m_unpackPremultiplyAlpha, data)) {
2735         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
2736         return;
2737     }
2738     if (m_unpackAlignment != 1)
2739         m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, 1);
2740     texImage2DBase(target, level, internalformat, pixels->width(), pixels->height(), 0,
2741                    format, type, data.data(), ec);
2742     if (m_unpackAlignment != 1)
2743         m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, m_unpackAlignment);
2744 }
2745
2746 void WebGLRenderingContext::texImage2D(unsigned target, unsigned level, unsigned internalformat,
2747                                        unsigned format, unsigned type, HTMLImageElement* image, ExceptionCode& ec)
2748 {
2749     ec = 0;
2750     if (isContextLost())
2751         return;
2752     if (!image || !image->cachedImage()) {
2753         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
2754         return;
2755     }
2756     checkOrigin(image);
2757     texImage2DImpl(target, level, internalformat, format, type, image->cachedImage()->image(),
2758                    m_unpackFlipY, m_unpackPremultiplyAlpha, ec);
2759 }
2760
2761 void WebGLRenderingContext::texImage2D(unsigned target, unsigned level, unsigned internalformat,
2762                                        unsigned format, unsigned type, HTMLCanvasElement* canvas, ExceptionCode& ec)
2763 {
2764     ec = 0;
2765     if (isContextLost())
2766         return;
2767     if (!canvas || !canvas->buffer()) {
2768         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
2769         return;
2770     }
2771     checkOrigin(canvas);
2772     texImage2DImpl(target, level, internalformat, format, type, canvas->copiedImage(),
2773                    m_unpackFlipY, m_unpackPremultiplyAlpha, ec);
2774 }
2775
2776 PassRefPtr<Image> WebGLRenderingContext::videoFrameToImage(HTMLVideoElement* video)
2777 {
2778     if (!video || !video->videoWidth() || !video->videoHeight()) {
2779         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
2780         return 0;
2781     }
2782     IntSize size(video->videoWidth(), video->videoHeight());
2783     ImageBuffer* buf = m_videoCache.imageBuffer(size);
2784     if (!buf) {
2785         m_context->synthesizeGLError(GraphicsContext3D::OUT_OF_MEMORY);
2786         return 0;
2787     }
2788     checkOrigin(video);
2789     IntRect destRect(0, 0, size.width(), size.height());
2790     // FIXME: Turn this into a GPU-GPU texture copy instead of CPU readback.
2791     video->paintCurrentFrameInContext(buf->context(), destRect);
2792     return buf->copyImage();
2793 }
2794
2795 void WebGLRenderingContext::texImage2D(unsigned target, unsigned level, unsigned internalformat,
2796                                        unsigned format, unsigned type, HTMLVideoElement* video, ExceptionCode& ec)
2797 {
2798     ec = 0;
2799     if (isContextLost())
2800         return;
2801     RefPtr<Image> image = videoFrameToImage(video);
2802     if (!video)
2803         return;
2804     texImage2DImpl(target, level, internalformat, format, type, image.get(), m_unpackFlipY, m_unpackPremultiplyAlpha, ec);
2805 }
2806
2807 void WebGLRenderingContext::texParameter(unsigned long target, unsigned long pname, float paramf, int parami, bool isFloat)
2808 {
2809     if (isContextLost())
2810         return;
2811     WebGLTexture* tex = validateTextureBinding(target, false);
2812     if (!tex)
2813         return;
2814     switch (pname) {
2815     case GraphicsContext3D::TEXTURE_MIN_FILTER:
2816     case GraphicsContext3D::TEXTURE_MAG_FILTER:
2817         break;
2818     case GraphicsContext3D::TEXTURE_WRAP_S:
2819     case GraphicsContext3D::TEXTURE_WRAP_T:
2820         if ((isFloat && paramf != GraphicsContext3D::CLAMP_TO_EDGE && paramf != GraphicsContext3D::MIRRORED_REPEAT && paramf != GraphicsContext3D::REPEAT)
2821             || (!isFloat && parami != GraphicsContext3D::CLAMP_TO_EDGE && parami != GraphicsContext3D::MIRRORED_REPEAT && parami != GraphicsContext3D::REPEAT)) {
2822             m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
2823             return;
2824         }
2825         break;
2826     default:
2827         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
2828         return;
2829     }
2830     if (isFloat) {
2831         tex->setParameterf(pname, paramf);
2832         m_context->texParameterf(target, pname, paramf);
2833     } else {
2834         tex->setParameteri(pname, parami);
2835         m_context->texParameteri(target, pname, parami);
2836     }
2837     cleanupAfterGraphicsCall(false);
2838 }
2839
2840 void WebGLRenderingContext::texParameterf(unsigned target, unsigned pname, float param)
2841 {
2842     texParameter(target, pname, param, 0, true);
2843 }
2844
2845 void WebGLRenderingContext::texParameteri(unsigned target, unsigned pname, int param)
2846 {
2847     texParameter(target, pname, 0, param, false);
2848 }
2849
2850 void WebGLRenderingContext::texSubImage2DBase(unsigned target, unsigned level, int xoffset, int yoffset,
2851                                               int width, int height,
2852                                               unsigned format, unsigned type, void* pixels, ExceptionCode& ec)
2853 {
2854     // FIXME: For now we ignore any errors returned
2855     ec = 0;
2856     if (isContextLost())
2857         return;
2858     if (!validateTexFuncFormatAndType(format, type))
2859         return;
2860     if (!validateTextureBinding(target, true))
2861         return;
2862     if (!validateSize(xoffset, yoffset) || !validateSize(width, height))
2863         return;
2864     m_context->texSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels);
2865     cleanupAfterGraphicsCall(false);
2866 }
2867
2868 void WebGLRenderingContext::texSubImage2DImpl(unsigned target, unsigned level, int xoffset, int yoffset,
2869                                               unsigned format, unsigned type,
2870                                               Image* image, bool flipY, bool premultiplyAlpha, ExceptionCode& ec)
2871 {
2872     ec = 0;
2873     if (isContextLost())
2874         return;
2875     Vector<uint8_t> data;
2876     if (!m_context->extractImageData(image, format, type, flipY, premultiplyAlpha, m_unpackColorspaceConversion == GraphicsContext3D::NONE, data)) {
2877         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
2878         return;
2879     }
2880     texSubImage2DBase(target, level, xoffset, yoffset, image->width(), image->height(),
2881                       format, type, data.data(), ec);
2882 }
2883
2884 void WebGLRenderingContext::texSubImage2D(unsigned target, unsigned level, int xoffset, int yoffset,
2885                                           int width, int height,
2886                                           unsigned format, unsigned type, ArrayBufferView* pixels, ExceptionCode& ec)
2887 {
2888     if (isContextLost() || !validateTexFuncData(width, height, format, type, pixels))
2889         return;
2890     void* data = pixels ? pixels->baseAddress() : 0;
2891     Vector<uint8_t> tempData;
2892     bool changeUnpackAlignment = false;
2893     if (data && (m_unpackFlipY || m_unpackPremultiplyAlpha)) {
2894         if (!m_context->extractTextureData(width, height, format, type,
2895                                            m_unpackAlignment,
2896                                            m_unpackFlipY, m_unpackPremultiplyAlpha,
2897                                            data,
2898                                            tempData))
2899             return;
2900         data = tempData.data();
2901         changeUnpackAlignment = true;
2902     }
2903     if (changeUnpackAlignment)
2904         m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, 1);
2905     texSubImage2DBase(target, level, xoffset, yoffset, width, height, format, type, data, ec);
2906     if (changeUnpackAlignment)
2907         m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, m_unpackAlignment);
2908 }
2909
2910 void WebGLRenderingContext::texSubImage2D(unsigned target, unsigned level, int xoffset, int yoffset,
2911                                           unsigned format, unsigned type, ImageData* pixels, ExceptionCode& ec)
2912 {
2913     ec = 0;
2914     if (isContextLost())
2915         return;
2916     Vector<uint8_t> data;
2917     if (!m_context->extractImageData(pixels, format, type, m_unpackFlipY, m_unpackPremultiplyAlpha, data)) {
2918         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
2919         return;
2920     }
2921     texSubImage2DBase(target, level, xoffset, yoffset, pixels->width(), pixels->height(),
2922                       format, type, data.data(), ec);
2923 }
2924
2925 void WebGLRenderingContext::texSubImage2D(unsigned target, unsigned level, int xoffset, int yoffset,
2926                                           unsigned format, unsigned type, HTMLImageElement* image, ExceptionCode& ec)
2927 {
2928     ec = 0;
2929     if (isContextLost())
2930         return;
2931     if (!image || !image->cachedImage()) {
2932         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
2933         return;
2934     }
2935     checkOrigin(image);
2936     texSubImage2DImpl(target, level, xoffset, yoffset, format, type, image->cachedImage()->image(),
2937                       m_unpackFlipY, m_unpackPremultiplyAlpha, ec);
2938 }
2939
2940 void WebGLRenderingContext::texSubImage2D(unsigned target, unsigned level, int xoffset, int yoffset,
2941                                           unsigned format, unsigned type, HTMLCanvasElement* canvas, ExceptionCode& ec)
2942 {
2943     ec = 0;
2944     if (isContextLost())
2945         return;
2946     if (!canvas || !canvas->buffer()) {
2947         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
2948         return;
2949     }
2950     checkOrigin(canvas);
2951     texSubImage2DImpl(target, level, xoffset, yoffset, format, type, canvas->copiedImage(),
2952                       m_unpackFlipY, m_unpackPremultiplyAlpha, ec);
2953 }
2954
2955 void WebGLRenderingContext::texSubImage2D(unsigned target, unsigned level, int xoffset, int yoffset,
2956                                           unsigned format, unsigned type, HTMLVideoElement* video, ExceptionCode& ec)
2957 {
2958     ec = 0;
2959     if (isContextLost())
2960         return;
2961     RefPtr<Image> image = videoFrameToImage(video);
2962     if (!video)
2963         return;
2964     texSubImage2DImpl(target, level, xoffset, yoffset, format, type, image.get(), m_unpackFlipY, m_unpackPremultiplyAlpha, ec);
2965 }
2966
2967 void WebGLRenderingContext::uniform1f(const WebGLUniformLocation* location, float x, ExceptionCode& ec)
2968 {
2969     UNUSED_PARAM(ec);
2970     if (isContextLost() || !location)
2971         return;
2972
2973     if (location->program() != m_currentProgram) {
2974         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
2975         return;
2976     }
2977
2978     m_context->uniform1f(location->location(), x);
2979     cleanupAfterGraphicsCall(false);
2980 }
2981
2982 void WebGLRenderingContext::uniform1fv(const WebGLUniformLocation* location, Float32Array* v, ExceptionCode& ec)
2983 {
2984     UNUSED_PARAM(ec);
2985     if (isContextLost() || !validateUniformParameters(location, v, 1))
2986         return;
2987
2988     m_context->uniform1fv(location->location(), v->data(), v->length());
2989     cleanupAfterGraphicsCall(false);
2990 }
2991
2992 void WebGLRenderingContext::uniform1fv(const WebGLUniformLocation* location, float* v, int size, ExceptionCode& ec)
2993 {
2994     UNUSED_PARAM(ec);
2995     if (isContextLost() || !validateUniformParameters(location, v, size, 1))
2996         return;
2997
2998     m_context->uniform1fv(location->location(), v, size);
2999     cleanupAfterGraphicsCall(false);
3000 }
3001
3002 void WebGLRenderingContext::uniform1i(const WebGLUniformLocation* location, int x, ExceptionCode& ec)
3003 {
3004     UNUSED_PARAM(ec);
3005     if (isContextLost() || !location)
3006         return;
3007
3008     if (location->program() != m_currentProgram) {
3009         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
3010         return;
3011     }
3012
3013     m_context->uniform1i(location->location(), x);
3014     cleanupAfterGraphicsCall(false);
3015 }
3016
3017 void WebGLRenderingContext::uniform1iv(const WebGLUniformLocation* location, Int32Array* v, ExceptionCode& ec)
3018 {
3019     UNUSED_PARAM(ec);
3020     if (isContextLost() || !validateUniformParameters(location, v, 1))
3021         return;
3022
3023     m_context->uniform1iv(location->location(), v->data(), v->length());
3024     cleanupAfterGraphicsCall(false);
3025 }
3026
3027 void WebGLRenderingContext::uniform1iv(const WebGLUniformLocation* location, int* v, int size, ExceptionCode& ec)
3028 {
3029     UNUSED_PARAM(ec);
3030     if (isContextLost() || !validateUniformParameters(location, v, size, 1))
3031         return;
3032
3033     m_context->uniform1iv(location->location(), v, size);
3034     cleanupAfterGraphicsCall(false);
3035 }
3036
3037 void WebGLRenderingContext::uniform2f(const WebGLUniformLocation* location, float x, float y, ExceptionCode& ec)
3038 {
3039     UNUSED_PARAM(ec);
3040     if (isContextLost() || !location)
3041         return;
3042
3043     if (location->program() != m_currentProgram) {
3044         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
3045         return;
3046     }
3047
3048     m_context->uniform2f(location->location(), x, y);
3049     cleanupAfterGraphicsCall(false);
3050 }
3051
3052 void WebGLRenderingContext::uniform2fv(const WebGLUniformLocation* location, Float32Array* v, ExceptionCode& ec)
3053 {
3054     UNUSED_PARAM(ec);
3055     if (isContextLost() || !validateUniformParameters(location, v, 2))
3056         return;
3057
3058     m_context->uniform2fv(location->location(), v->data(), v->length() / 2);
3059     cleanupAfterGraphicsCall(false);
3060 }
3061
3062 void WebGLRenderingContext::uniform2fv(const WebGLUniformLocation* location, float* v, int size, ExceptionCode& ec)
3063 {
3064     UNUSED_PARAM(ec);
3065     if (isContextLost() || !validateUniformParameters(location, v, size, 2))
3066         return;
3067
3068     m_context->uniform2fv(location->location(), v, size / 2);
3069     cleanupAfterGraphicsCall(false);
3070 }
3071
3072 void WebGLRenderingContext::uniform2i(const WebGLUniformLocation* location, int x, int y, ExceptionCode& ec)
3073 {
3074     UNUSED_PARAM(ec);
3075     if (isContextLost() || !location)
3076         return;
3077
3078     if (location->program() != m_currentProgram) {
3079         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
3080         return;
3081     }
3082
3083     m_context->uniform2i(location->location(), x, y);
3084     cleanupAfterGraphicsCall(false);
3085 }
3086
3087 void WebGLRenderingContext::uniform2iv(const WebGLUniformLocation* location, Int32Array* v, ExceptionCode& ec)
3088 {
3089     UNUSED_PARAM(ec);
3090     if (isContextLost() || !validateUniformParameters(location, v, 2))
3091         return;
3092
3093     m_context->uniform2iv(location->location(), v->data(), v->length() / 2);
3094     cleanupAfterGraphicsCall(false);
3095 }
3096
3097 void WebGLRenderingContext::uniform2iv(const WebGLUniformLocation* location, int* v, int size, ExceptionCode& ec)
3098 {
3099     UNUSED_PARAM(ec);
3100     if (isContextLost() || !validateUniformParameters(location, v, size, 2))
3101         return;
3102
3103     m_context->uniform2iv(location->location(), v, size / 2);
3104     cleanupAfterGraphicsCall(false);
3105 }
3106
3107 void WebGLRenderingContext::uniform3f(const WebGLUniformLocation* location, float x, float y, float z, ExceptionCode& ec)
3108 {
3109     UNUSED_PARAM(ec);
3110     if (isContextLost() || !location)
3111         return;
3112
3113     if (location->program() != m_currentProgram) {
3114         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
3115         return;
3116     }
3117
3118     m_context->uniform3f(location->location(), x, y, z);
3119     cleanupAfterGraphicsCall(false);
3120 }
3121
3122 void WebGLRenderingContext::uniform3fv(const WebGLUniformLocation* location, Float32Array* v, ExceptionCode& ec)
3123 {
3124     UNUSED_PARAM(ec);
3125     if (isContextLost() || !validateUniformParameters(location, v, 3))
3126         return;
3127
3128     m_context->uniform3fv(location->location(), v->data(), v->length() / 3);
3129     cleanupAfterGraphicsCall(false);
3130 }
3131
3132 void WebGLRenderingContext::uniform3fv(const WebGLUniformLocation* location, float* v, int size, ExceptionCode& ec)
3133 {
3134     UNUSED_PARAM(ec);
3135     if (isContextLost() || !validateUniformParameters(location, v, size, 3))
3136         return;
3137
3138     m_context->uniform3fv(location->location(), v, size / 3);
3139     cleanupAfterGraphicsCall(false);
3140 }
3141
3142 void WebGLRenderingContext::uniform3i(const WebGLUniformLocation* location, int x, int y, int z, ExceptionCode& ec)
3143 {
3144     UNUSED_PARAM(ec);
3145     if (isContextLost() || !location)
3146         return;
3147
3148     if (location->program() != m_currentProgram) {
3149         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
3150         return;
3151     }
3152
3153     m_context->uniform3i(location->location(), x, y, z);
3154     cleanupAfterGraphicsCall(false);
3155 }
3156
3157 void WebGLRenderingContext::uniform3iv(const WebGLUniformLocation* location, Int32Array* v, ExceptionCode& ec)
3158 {
3159     UNUSED_PARAM(ec);
3160     if (isContextLost() || !validateUniformParameters(location, v, 3))
3161         return;
3162
3163     m_context->uniform3iv(location->location(), v->data(), v->length() / 3);
3164     cleanupAfterGraphicsCall(false);
3165 }
3166
3167 void WebGLRenderingContext::uniform3iv(const WebGLUniformLocation* location, int* v, int size, ExceptionCode& ec)
3168 {
3169     UNUSED_PARAM(ec);
3170     if (isContextLost() || !validateUniformParameters(location, v, size, 3))
3171         return;
3172
3173     m_context->uniform3iv(location->location(), v, size / 3);
3174     cleanupAfterGraphicsCall(false);
3175 }
3176
3177 void WebGLRenderingContext::uniform4f(const WebGLUniformLocation* location, float x, float y, float z, float w, ExceptionCode& ec)
3178 {
3179     UNUSED_PARAM(ec);
3180     if (isContextLost() || !location)
3181         return;
3182
3183     if (location->program() != m_currentProgram) {
3184         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
3185         return;
3186     }
3187
3188     m_context->uniform4f(location->location(), x, y, z, w);
3189     cleanupAfterGraphicsCall(false);
3190 }
3191
3192 void WebGLRenderingContext::uniform4fv(const WebGLUniformLocation* location, Float32Array* v, ExceptionCode& ec)
3193 {
3194     UNUSED_PARAM(ec);
3195     if (isContextLost() || !validateUniformParameters(location, v, 4))
3196         return;
3197
3198     m_context->uniform4fv(location->location(), v->data(), v->length() / 4);
3199     cleanupAfterGraphicsCall(false);
3200 }
3201
3202 void WebGLRenderingContext::uniform4fv(const WebGLUniformLocation* location, float* v, int size, ExceptionCode& ec)
3203 {
3204     UNUSED_PARAM(ec);
3205     if (isContextLost() || !validateUniformParameters(location, v, size, 4))
3206         return;
3207
3208     m_context->uniform4fv(location->location(), v, size / 4);
3209     cleanupAfterGraphicsCall(false);
3210 }
3211
3212 void WebGLRenderingContext::uniform4i(const WebGLUniformLocation* location, int x, int y, int z, int w, ExceptionCode& ec)
3213 {
3214     UNUSED_PARAM(ec);
3215     if (isContextLost() || !location)
3216         return;
3217
3218     if (location->program() != m_currentProgram) {
3219         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
3220         return;
3221     }
3222
3223     m_context->uniform4i(location->location(), x, y, z, w);
3224     cleanupAfterGraphicsCall(false);
3225 }
3226
3227 void WebGLRenderingContext::uniform4iv(const WebGLUniformLocation* location, Int32Array* v, ExceptionCode& ec)
3228 {
3229     UNUSED_PARAM(ec);
3230     if (isContextLost() || !validateUniformParameters(location, v, 4))
3231         return;
3232
3233     m_context->uniform4iv(location->location(), v->data(), v->length() / 4);
3234     cleanupAfterGraphicsCall(false);
3235 }
3236
3237 void WebGLRenderingContext::uniform4iv(const WebGLUniformLocation* location, int* v, int size, ExceptionCode& ec)
3238 {
3239     UNUSED_PARAM(ec);
3240     if (isContextLost() || !validateUniformParameters(location, v, size, 4))
3241         return;
3242
3243     m_context->uniform4iv(location->location(), v, size / 4);
3244     cleanupAfterGraphicsCall(false);
3245 }
3246
3247 void WebGLRenderingContext::uniformMatrix2fv(const WebGLUniformLocation* location, bool transpose, Float32Array* v, ExceptionCode& ec)
3248 {
3249     UNUSED_PARAM(ec);
3250     if (isContextLost() || !validateUniformMatrixParameters(location, transpose, v, 4))
3251         return;
3252     m_context->uniformMatrix2fv(location->location(), transpose, v->data(), v->length() / 4);
3253     cleanupAfterGraphicsCall(false);
3254 }
3255
3256 void WebGLRenderingContext::uniformMatrix2fv(const WebGLUniformLocation* location, bool transpose, float* v, int size, ExceptionCode& ec)
3257 {
3258     UNUSED_PARAM(ec);
3259     if (isContextLost() || !validateUniformMatrixParameters(location, transpose, v, size, 4))
3260         return;
3261     m_context->uniformMatrix2fv(location->location(), transpose, v, size / 4);
3262     cleanupAfterGraphicsCall(false);
3263 }
3264
3265 void WebGLRenderingContext::uniformMatrix3fv(const WebGLUniformLocation* location, bool transpose, Float32Array* v, ExceptionCode& ec)
3266 {
3267     UNUSED_PARAM(ec);
3268     if (isContextLost() || !validateUniformMatrixParameters(location, transpose, v, 9))
3269         return;
3270     m_context->uniformMatrix3fv(location->location(), transpose, v->data(), v->length() / 9);
3271     cleanupAfterGraphicsCall(false);
3272 }
3273
3274 void WebGLRenderingContext::uniformMatrix3fv(const WebGLUniformLocation* location, bool transpose, float* v, int size, ExceptionCode& ec)
3275 {
3276     UNUSED_PARAM(ec);
3277     if (isContextLost() || !validateUniformMatrixParameters(location, transpose, v, size, 9))
3278         return;
3279     m_context->uniformMatrix3fv(location->location(), transpose, v, size / 9);
3280     cleanupAfterGraphicsCall(false);
3281 }
3282
3283 void WebGLRenderingContext::uniformMatrix4fv(const WebGLUniformLocation* location, bool transpose, Float32Array* v, ExceptionCode& ec)
3284 {
3285     UNUSED_PARAM(ec);
3286     if (isContextLost() || !validateUniformMatrixParameters(location, transpose, v, 16))
3287         return;
3288     m_context->uniformMatrix4fv(location->location(), transpose, v->data(), v->length() / 16);
3289     cleanupAfterGraphicsCall(false);
3290 }
3291
3292 void WebGLRenderingContext::uniformMatrix4fv(const WebGLUniformLocation* location, bool transpose, float* v, int size, ExceptionCode& ec)
3293 {
3294     UNUSED_PARAM(ec);
3295     if (isContextLost() || !validateUniformMatrixParameters(location, transpose, v, size, 16))
3296         return;
3297     m_context->uniformMatrix4fv(location->location(), transpose, v, size / 16);
3298     cleanupAfterGraphicsCall(false);
3299 }
3300
3301 void WebGLRenderingContext::useProgram(WebGLProgram* program, ExceptionCode& ec)
3302 {
3303     UNUSED_PARAM(ec);
3304     if (isContextLost())
3305         return;
3306     if (program && program->context() != this) {
3307         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
3308         return;
3309     }
3310     if (program && program->object() && !program->getLinkStatus()) {
3311         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
3312         cleanupAfterGraphicsCall(false);
3313         return;
3314     }
3315     if (m_currentProgram != program) {
3316         if (m_currentProgram)
3317             m_currentProgram->onDetached();
3318         m_currentProgram = program;
3319         m_context->useProgram(objectOrZero(program));
3320         if (program && program->object())
3321             program->onAttached();
3322     }
3323     cleanupAfterGraphicsCall(false);
3324 }
3325
3326 void WebGLRenderingContext::validateProgram(WebGLProgram* program, ExceptionCode& ec)
3327 {
3328     UNUSED_PARAM(ec);
3329     if (isContextLost() || !validateWebGLObject(program))
3330         return;
3331     m_context->validateProgram(objectOrZero(program));
3332     cleanupAfterGraphicsCall(false);
3333 }
3334
3335 void WebGLRenderingContext::vertexAttrib1f(unsigned long index, float v0)
3336 {
3337     vertexAttribfImpl(index, 1, v0, 0.0f, 0.0f, 1.0f);
3338 }
3339
3340 void WebGLRenderingContext::vertexAttrib1fv(unsigned long index, Float32Array* v)
3341 {
3342     vertexAttribfvImpl(index, v, 1);
3343 }
3344
3345 void WebGLRenderingContext::vertexAttrib1fv(unsigned long index, float* v, int size)
3346 {
3347     vertexAttribfvImpl(index, v, size, 1);
3348 }
3349
3350 void WebGLRenderingContext::vertexAttrib2f(unsigned long index, float v0, float v1)
3351 {
3352     vertexAttribfImpl(index, 2, v0, v1, 0.0f, 1.0f);
3353 }
3354
3355 void WebGLRenderingContext::vertexAttrib2fv(unsigned long index, Float32Array* v)
3356 {
3357     vertexAttribfvImpl(index, v, 2);
3358 }
3359
3360 void WebGLRenderingContext::vertexAttrib2fv(unsigned long index, float* v, int size)
3361 {
3362     vertexAttribfvImpl(index, v, size, 2);
3363 }
3364
3365 void WebGLRenderingContext::vertexAttrib3f(unsigned long index, float v0, float v1, float v2)
3366 {
3367     vertexAttribfImpl(index, 3, v0, v1, v2, 1.0f);
3368 }
3369
3370 void WebGLRenderingContext::vertexAttrib3fv(unsigned long index, Float32Array* v)
3371 {
3372     vertexAttribfvImpl(index, v, 3);
3373 }
3374