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