2010-07-02 Zhenyao Mo <zmo@google.com>
[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 (!validateUniformParameters(location, v, 1))
2502         return;
2503
2504     m_context->uniform1fv(location->location(), v->data(), v->length());
2505     cleanupAfterGraphicsCall(false);
2506 }
2507
2508 void WebGLRenderingContext::uniform1fv(const WebGLUniformLocation* location, float* v, int size, ExceptionCode& ec)
2509 {
2510     UNUSED_PARAM(ec);
2511     if (!validateUniformParameters(location, v, size, 1))
2512         return;
2513
2514     m_context->uniform1fv(location->location(), v, size);
2515     cleanupAfterGraphicsCall(false);
2516 }
2517
2518 void WebGLRenderingContext::uniform1i(const WebGLUniformLocation* location, int x, ExceptionCode& ec)
2519 {
2520     UNUSED_PARAM(ec);
2521     if (!location)
2522         return;
2523
2524     if (location->program() != m_currentProgram) {
2525         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
2526         return;
2527     }
2528
2529     m_context->uniform1i(location->location(), x);
2530     cleanupAfterGraphicsCall(false);
2531 }
2532
2533 void WebGLRenderingContext::uniform1iv(const WebGLUniformLocation* location, Int32Array* v, ExceptionCode& ec)
2534 {
2535     UNUSED_PARAM(ec);
2536     if (!validateUniformParameters(location, v, 1))
2537         return;
2538
2539     m_context->uniform1iv(location->location(), v->data(), v->length());
2540     cleanupAfterGraphicsCall(false);
2541 }
2542
2543 void WebGLRenderingContext::uniform1iv(const WebGLUniformLocation* location, int* v, int size, ExceptionCode& ec)
2544 {
2545     UNUSED_PARAM(ec);
2546     if (!validateUniformParameters(location, v, size, 1))
2547         return;
2548
2549     m_context->uniform1iv(location->location(), v, size);
2550     cleanupAfterGraphicsCall(false);
2551 }
2552
2553 void WebGLRenderingContext::uniform2f(const WebGLUniformLocation* location, float x, float y, ExceptionCode& ec)
2554 {
2555     UNUSED_PARAM(ec);
2556     if (!location)
2557         return;
2558
2559     if (location->program() != m_currentProgram) {
2560         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
2561         return;
2562     }
2563
2564     m_context->uniform2f(location->location(), x, y);
2565     cleanupAfterGraphicsCall(false);
2566 }
2567
2568 void WebGLRenderingContext::uniform2fv(const WebGLUniformLocation* location, Float32Array* v, ExceptionCode& ec)
2569 {
2570     UNUSED_PARAM(ec);
2571     if (!validateUniformParameters(location, v, 2))
2572         return;
2573
2574     m_context->uniform2fv(location->location(), v->data(), v->length() / 2);
2575     cleanupAfterGraphicsCall(false);
2576 }
2577
2578 void WebGLRenderingContext::uniform2fv(const WebGLUniformLocation* location, float* v, int size, ExceptionCode& ec)
2579 {
2580     UNUSED_PARAM(ec);
2581     if (!validateUniformParameters(location, v, size, 2))
2582         return;
2583
2584     m_context->uniform2fv(location->location(), v, size / 2);
2585     cleanupAfterGraphicsCall(false);
2586 }
2587
2588 void WebGLRenderingContext::uniform2i(const WebGLUniformLocation* location, int x, int y, ExceptionCode& ec)
2589 {
2590     UNUSED_PARAM(ec);
2591     if (!location)
2592         return;
2593
2594     if (location->program() != m_currentProgram) {
2595         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
2596         return;
2597     }
2598
2599     m_context->uniform2i(location->location(), x, y);
2600     cleanupAfterGraphicsCall(false);
2601 }
2602
2603 void WebGLRenderingContext::uniform2iv(const WebGLUniformLocation* location, Int32Array* v, ExceptionCode& ec)
2604 {
2605     UNUSED_PARAM(ec);
2606     if (!validateUniformParameters(location, v, 2))
2607         return;
2608
2609     m_context->uniform2iv(location->location(), v->data(), v->length() / 2);
2610     cleanupAfterGraphicsCall(false);
2611 }
2612
2613 void WebGLRenderingContext::uniform2iv(const WebGLUniformLocation* location, int* v, int size, ExceptionCode& ec)
2614 {
2615     UNUSED_PARAM(ec);
2616     if (!validateUniformParameters(location, v, size, 2))
2617         return;
2618
2619     m_context->uniform2iv(location->location(), v, size / 2);
2620     cleanupAfterGraphicsCall(false);
2621 }
2622
2623 void WebGLRenderingContext::uniform3f(const WebGLUniformLocation* location, float x, float y, float z, ExceptionCode& ec)
2624 {
2625     UNUSED_PARAM(ec);
2626     if (!location)
2627         return;
2628
2629     if (location->program() != m_currentProgram) {
2630         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
2631         return;
2632     }
2633
2634     m_context->uniform3f(location->location(), x, y, z);
2635     cleanupAfterGraphicsCall(false);
2636 }
2637
2638 void WebGLRenderingContext::uniform3fv(const WebGLUniformLocation* location, Float32Array* v, ExceptionCode& ec)
2639 {
2640     UNUSED_PARAM(ec);
2641     if (!validateUniformParameters(location, v, 3))
2642         return;
2643
2644     m_context->uniform3fv(location->location(), v->data(), v->length() / 3);
2645     cleanupAfterGraphicsCall(false);
2646 }
2647
2648 void WebGLRenderingContext::uniform3fv(const WebGLUniformLocation* location, float* v, int size, ExceptionCode& ec)
2649 {
2650     UNUSED_PARAM(ec);
2651     if (!validateUniformParameters(location, v, size, 3))
2652         return;
2653
2654     m_context->uniform3fv(location->location(), v, size / 3);
2655     cleanupAfterGraphicsCall(false);
2656 }
2657
2658 void WebGLRenderingContext::uniform3i(const WebGLUniformLocation* location, int x, int y, int z, ExceptionCode& ec)
2659 {
2660     UNUSED_PARAM(ec);
2661     if (!location)
2662         return;
2663
2664     if (location->program() != m_currentProgram) {
2665         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
2666         return;
2667     }
2668
2669     m_context->uniform3i(location->location(), x, y, z);
2670     cleanupAfterGraphicsCall(false);
2671 }
2672
2673 void WebGLRenderingContext::uniform3iv(const WebGLUniformLocation* location, Int32Array* v, ExceptionCode& ec)
2674 {
2675     UNUSED_PARAM(ec);
2676     if (!validateUniformParameters(location, v, 3))
2677         return;
2678
2679     m_context->uniform3iv(location->location(), v->data(), v->length() / 3);
2680     cleanupAfterGraphicsCall(false);
2681 }
2682
2683 void WebGLRenderingContext::uniform3iv(const WebGLUniformLocation* location, int* v, int size, ExceptionCode& ec)
2684 {
2685     UNUSED_PARAM(ec);
2686     if (!validateUniformParameters(location, v, size, 3))
2687         return;
2688
2689     m_context->uniform3iv(location->location(), v, size / 3);
2690     cleanupAfterGraphicsCall(false);
2691 }
2692
2693 void WebGLRenderingContext::uniform4f(const WebGLUniformLocation* location, float x, float y, float z, float w, ExceptionCode& ec)
2694 {
2695     UNUSED_PARAM(ec);
2696     if (!location)
2697         return;
2698
2699     if (location->program() != m_currentProgram) {
2700         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
2701         return;
2702     }
2703
2704     m_context->uniform4f(location->location(), x, y, z, w);
2705     cleanupAfterGraphicsCall(false);
2706 }
2707
2708 void WebGLRenderingContext::uniform4fv(const WebGLUniformLocation* location, Float32Array* v, ExceptionCode& ec)
2709 {
2710     UNUSED_PARAM(ec);
2711     if (!validateUniformParameters(location, v, 4))
2712         return;
2713
2714     m_context->uniform4fv(location->location(), v->data(), v->length() / 4);
2715     cleanupAfterGraphicsCall(false);
2716 }
2717
2718 void WebGLRenderingContext::uniform4fv(const WebGLUniformLocation* location, float* v, int size, ExceptionCode& ec)
2719 {
2720     UNUSED_PARAM(ec);
2721     if (!validateUniformParameters(location, v, size, 4))
2722         return;
2723
2724     m_context->uniform4fv(location->location(), v, size / 4);
2725     cleanupAfterGraphicsCall(false);
2726 }
2727
2728 void WebGLRenderingContext::uniform4i(const WebGLUniformLocation* location, int x, int y, int z, int w, ExceptionCode& ec)
2729 {
2730     UNUSED_PARAM(ec);
2731     if (!location)
2732         return;
2733
2734     if (location->program() != m_currentProgram) {
2735         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
2736         return;
2737     }
2738
2739     m_context->uniform4i(location->location(), x, y, z, w);
2740     cleanupAfterGraphicsCall(false);
2741 }
2742
2743 void WebGLRenderingContext::uniform4iv(const WebGLUniformLocation* location, Int32Array* v, ExceptionCode& ec)
2744 {
2745     UNUSED_PARAM(ec);
2746     if (!validateUniformParameters(location, v, 4))
2747         return;
2748
2749     m_context->uniform4iv(location->location(), v->data(), v->length() / 4);
2750     cleanupAfterGraphicsCall(false);
2751 }
2752
2753 void WebGLRenderingContext::uniform4iv(const WebGLUniformLocation* location, int* v, int size, ExceptionCode& ec)
2754 {
2755     UNUSED_PARAM(ec);
2756     if (!validateUniformParameters(location, v, size, 4))
2757         return;
2758
2759     m_context->uniform4iv(location->location(), v, size / 4);
2760     cleanupAfterGraphicsCall(false);
2761 }
2762
2763 void WebGLRenderingContext::uniformMatrix2fv(const WebGLUniformLocation* location, bool transpose, Float32Array* v, ExceptionCode& ec)
2764 {
2765     UNUSED_PARAM(ec);
2766     if (!validateUniformMatrixParameters(location, transpose, v, 4))
2767         return;
2768     m_context->uniformMatrix2fv(location->location(), transpose, v->data(), v->length() / 4);
2769     cleanupAfterGraphicsCall(false);
2770 }
2771
2772 void WebGLRenderingContext::uniformMatrix2fv(const WebGLUniformLocation* location, bool transpose, float* v, int size, ExceptionCode& ec)
2773 {
2774     UNUSED_PARAM(ec);
2775     if (!validateUniformMatrixParameters(location, transpose, v, size, 4))
2776         return;
2777     m_context->uniformMatrix2fv(location->location(), transpose, v, size / 4);
2778     cleanupAfterGraphicsCall(false);
2779 }
2780
2781 void WebGLRenderingContext::uniformMatrix3fv(const WebGLUniformLocation* location, bool transpose, Float32Array* v, ExceptionCode& ec)
2782 {
2783     UNUSED_PARAM(ec);
2784     if (!validateUniformMatrixParameters(location, transpose, v, 9))
2785         return;
2786     m_context->uniformMatrix3fv(location->location(), transpose, v->data(), v->length() / 9);
2787     cleanupAfterGraphicsCall(false);
2788 }
2789
2790 void WebGLRenderingContext::uniformMatrix3fv(const WebGLUniformLocation* location, bool transpose, float* v, int size, ExceptionCode& ec)
2791 {
2792     UNUSED_PARAM(ec);
2793     if (!validateUniformMatrixParameters(location, transpose, v, size, 9))
2794         return;
2795     m_context->uniformMatrix3fv(location->location(), transpose, v, size / 9);
2796     cleanupAfterGraphicsCall(false);
2797 }
2798
2799 void WebGLRenderingContext::uniformMatrix4fv(const WebGLUniformLocation* location, bool transpose, Float32Array* v, ExceptionCode& ec)
2800 {
2801     UNUSED_PARAM(ec);
2802     if (!validateUniformMatrixParameters(location, transpose, v, 16))
2803         return;
2804     m_context->uniformMatrix4fv(location->location(), transpose, v->data(), v->length() / 16);
2805     cleanupAfterGraphicsCall(false);
2806 }
2807
2808 void WebGLRenderingContext::uniformMatrix4fv(const WebGLUniformLocation* location, bool transpose, float* v, int size, ExceptionCode& ec)
2809 {
2810     UNUSED_PARAM(ec);
2811     if (!validateUniformMatrixParameters(location, transpose, v, size, 16))
2812         return;
2813     m_context->uniformMatrix4fv(location->location(), transpose, v, size / 16);
2814     cleanupAfterGraphicsCall(false);
2815 }
2816
2817 void WebGLRenderingContext::useProgram(WebGLProgram* program, ExceptionCode& ec)
2818 {
2819     UNUSED_PARAM(ec);
2820     if (program && program->context() != this) {
2821         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
2822         return;
2823     }
2824     m_currentProgram = program;
2825     m_context->useProgram(program);
2826     cleanupAfterGraphicsCall(false);
2827 }
2828
2829 void WebGLRenderingContext::validateProgram(WebGLProgram* program, ExceptionCode& ec)
2830 {
2831     UNUSED_PARAM(ec);
2832     if (!validateWebGLObject(program))
2833         return;
2834     m_context->validateProgram(program);
2835     cleanupAfterGraphicsCall(false);
2836 }
2837
2838 void WebGLRenderingContext::vertexAttrib1f(unsigned long indx, float v0)
2839 {
2840     m_context->vertexAttrib1f(indx, v0);
2841     cleanupAfterGraphicsCall(false);
2842 }
2843
2844 void WebGLRenderingContext::vertexAttrib1fv(unsigned long indx, Float32Array* v)
2845 {
2846     // FIXME: Need to make sure array is big enough for attribute being set
2847     m_context->vertexAttrib1fv(indx, v->data());
2848     cleanupAfterGraphicsCall(false);
2849 }
2850
2851 void WebGLRenderingContext::vertexAttrib1fv(unsigned long indx, float* v, int size)
2852 {
2853     // FIXME: Need to make sure array is big enough for attribute being set
2854     UNUSED_PARAM(size);
2855     
2856     m_context->vertexAttrib1fv(indx, v);
2857     cleanupAfterGraphicsCall(false);
2858 }
2859
2860 void WebGLRenderingContext::vertexAttrib2f(unsigned long indx, float v0, float v1)
2861 {
2862     m_context->vertexAttrib2f(indx, v0, v1);
2863     cleanupAfterGraphicsCall(false);
2864 }
2865
2866 void WebGLRenderingContext::vertexAttrib2fv(unsigned long indx, Float32Array* v)
2867 {
2868     // FIXME: Need to make sure array is big enough for attribute being set
2869     m_context->vertexAttrib2fv(indx, v->data());
2870     cleanupAfterGraphicsCall(false);
2871 }
2872
2873 void WebGLRenderingContext::vertexAttrib2fv(unsigned long indx, float* v, int size)
2874 {
2875     // FIXME: Need to make sure array is big enough for attribute being set
2876     UNUSED_PARAM(size);
2877     
2878     m_context->vertexAttrib2fv(indx, v);
2879     cleanupAfterGraphicsCall(false);
2880 }
2881
2882 void WebGLRenderingContext::vertexAttrib3f(unsigned long indx, float v0, float v1, float v2)
2883 {
2884     m_context->vertexAttrib3f(indx, v0, v1, v2);
2885     cleanupAfterGraphicsCall(false);
2886 }
2887
2888 void WebGLRenderingContext::vertexAttrib3fv(unsigned long indx, Float32Array* v)
2889 {
2890     // FIXME: Need to make sure array is big enough for attribute being set
2891     m_context->vertexAttrib3fv(indx, v->data());
2892     cleanupAfterGraphicsCall(false);
2893 }
2894
2895 void WebGLRenderingContext::vertexAttrib3fv(unsigned long indx, float* v, int size)
2896 {
2897     // FIXME: Need to make sure array is big enough for attribute being set
2898     UNUSED_PARAM(size);
2899     
2900     m_context->vertexAttrib3fv(indx, v);
2901     cleanupAfterGraphicsCall(false);
2902 }
2903
2904 void WebGLRenderingContext::vertexAttrib4f(unsigned long indx, float v0, float v1, float v2, float v3)
2905 {
2906     m_context->vertexAttrib4f(indx, v0, v1, v2, v3);
2907     cleanupAfterGraphicsCall(false);
2908 }
2909
2910 void WebGLRenderingContext::vertexAttrib4fv(unsigned long indx, Float32Array* v)
2911 {
2912     // FIXME: Need to make sure array is big enough for attribute being set
2913     m_context->vertexAttrib4fv(indx, v->data());
2914     cleanupAfterGraphicsCall(false);
2915 }
2916
2917 void WebGLRenderingContext::vertexAttrib4fv(unsigned long indx, float* v, int size)
2918 {
2919     // FIXME: Need to make sure array is big enough for attribute being set
2920     UNUSED_PARAM(size);
2921     
2922     m_context->vertexAttrib4fv(indx, v);
2923     cleanupAfterGraphicsCall(false);
2924 }
2925
2926 void WebGLRenderingContext::vertexAttribPointer(unsigned long indx, long size, unsigned long type, bool normalized, unsigned long stride, unsigned long offset, ExceptionCode& ec)
2927 {
2928     UNUSED_PARAM(ec);
2929     if (!m_boundArrayBuffer || indx >= m_maxVertexAttribs) {
2930         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
2931         return;
2932     }
2933     
2934     if (indx >= m_vertexAttribState.size())
2935         m_vertexAttribState.resize(indx + 1);
2936
2937     // Determine the number of elements the bound buffer can hold, given the offset, size, type and stride
2938     long bytesPerElement = size * sizeInBytes(type, ec);
2939     if (bytesPerElement <= 0)
2940         return;
2941     long validatedStride = bytesPerElement;
2942     if (stride != 0) {
2943         if ((long) stride < bytesPerElement) {
2944             m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
2945             return;
2946         }
2947         
2948         validatedStride = stride;
2949     }
2950     m_vertexAttribState[indx].bufferBinding = m_boundArrayBuffer;
2951     m_vertexAttribState[indx].bytesPerElement = bytesPerElement;
2952     m_vertexAttribState[indx].stride = validatedStride;
2953     m_vertexAttribState[indx].offset = offset;
2954     m_context->vertexAttribPointer(indx, size, type, normalized, stride, offset);
2955     cleanupAfterGraphicsCall(false);
2956 }
2957
2958 void WebGLRenderingContext::viewport(long x, long y, unsigned long width, unsigned long height)
2959 {
2960     if (isnan(x))
2961         x = 0;
2962     if (isnan(y))
2963         y = 0;
2964     if (isnan(width))
2965         width = 100;
2966     if (isnan(height))
2967         height = 100;
2968     m_context->viewport(x, y, width, height);
2969     cleanupAfterGraphicsCall(false);
2970 }
2971
2972 void WebGLRenderingContext::removeObject(CanvasObject* object)
2973 {
2974     m_canvasObjects.remove(object);
2975 }
2976
2977 void WebGLRenderingContext::addObject(CanvasObject* object)
2978 {
2979     removeObject(object);
2980     m_canvasObjects.add(object);
2981 }
2982
2983 void WebGLRenderingContext::detachAndRemoveAllObjects()
2984 {
2985     HashSet<RefPtr<CanvasObject> >::iterator pend = m_canvasObjects.end();
2986     for (HashSet<RefPtr<CanvasObject> >::iterator it = m_canvasObjects.begin(); it != pend; ++it)
2987         (*it)->detachContext();
2988         
2989     m_canvasObjects.clear();
2990 }
2991
2992 WebGLTexture* WebGLRenderingContext::findTexture(Platform3DObject obj)
2993 {
2994     if (!obj)
2995         return 0;
2996     HashSet<RefPtr<CanvasObject> >::iterator pend = m_canvasObjects.end();
2997     for (HashSet<RefPtr<CanvasObject> >::iterator it = m_canvasObjects.begin(); it != pend; ++it) {
2998         if ((*it)->isTexture() && (*it)->object() == obj)
2999             return reinterpret_cast<WebGLTexture*>((*it).get());
3000     }
3001     return 0;
3002 }
3003
3004 WebGLRenderbuffer* WebGLRenderingContext::findRenderbuffer(Platform3DObject obj)
3005 {
3006     if (!obj)
3007         return 0;
3008     HashSet<RefPtr<CanvasObject> >::iterator pend = m_canvasObjects.end();
3009     for (HashSet<RefPtr<CanvasObject> >::iterator it = m_canvasObjects.begin(); it != pend; ++it) {
3010         if ((*it)->isRenderbuffer() && (*it)->object() == obj)
3011             return reinterpret_cast<WebGLRenderbuffer*>((*it).get());
3012     }
3013     return 0;
3014 }
3015
3016 WebGLBuffer* WebGLRenderingContext::findBuffer(Platform3DObject obj)
3017 {
3018     if (!obj)
3019         return 0;
3020     HashSet<RefPtr<CanvasObject> >::iterator pend = m_canvasObjects.end();
3021     for (HashSet<RefPtr<CanvasObject> >::iterator it = m_canvasObjects.begin(); it != pend; ++it) {
3022         if ((*it)->isBuffer() && (*it)->object() == obj)
3023             return reinterpret_cast<WebGLBuffer*>((*it).get());
3024     }
3025     return 0;
3026 }
3027
3028 WebGLShader* WebGLRenderingContext::findShader(Platform3DObject obj)
3029 {
3030     if (!obj)
3031         return 0;
3032     HashSet<RefPtr<CanvasObject> >::iterator pend = m_canvasObjects.end();
3033     for (HashSet<RefPtr<CanvasObject> >::iterator it = m_canvasObjects.begin(); it != pend; ++it) {
3034         if ((*it)->isShader() && (*it)->object() == obj)
3035             return reinterpret_cast<WebGLShader*>((*it).get());
3036     }
3037     return 0;
3038 }
3039
3040 WebGLGetInfo WebGLRenderingContext::getBooleanParameter(unsigned long pname)
3041 {
3042     unsigned char value;
3043     m_context->getBooleanv(pname, &value);
3044     return WebGLGetInfo(static_cast<bool>(value));
3045 }
3046
3047 WebGLGetInfo WebGLRenderingContext::getBooleanArrayParameter(unsigned long pname)
3048 {
3049     if (pname != GraphicsContext3D::COLOR_WRITEMASK) {
3050         notImplemented();
3051         return WebGLGetInfo(0, 0);
3052     }
3053     unsigned char value[4] = {0};
3054     m_context->getBooleanv(pname, value);
3055     bool boolValue[4];
3056     for (int ii = 0; ii < 4; ++ii)
3057         boolValue[ii] = static_cast<bool>(value[ii]);
3058     return WebGLGetInfo(boolValue, 4);
3059 }
3060
3061 WebGLGetInfo WebGLRenderingContext::getFloatParameter(unsigned long pname)
3062 {
3063     float value;
3064     m_context->getFloatv(pname, &value);
3065     return WebGLGetInfo(static_cast<float>(value));
3066 }
3067
3068 WebGLGetInfo WebGLRenderingContext::getIntParameter(unsigned long pname)
3069 {
3070     return getLongParameter(pname);
3071 }
3072
3073 WebGLGetInfo WebGLRenderingContext::getLongParameter(unsigned long pname)
3074 {
3075     int value;
3076     m_context->getIntegerv(pname, &value);
3077     return WebGLGetInfo(static_cast<long>(value));
3078 }
3079
3080 WebGLGetInfo WebGLRenderingContext::getUnsignedLongParameter(unsigned long pname)
3081 {
3082     int value;
3083     m_context->getIntegerv(pname, &value);
3084     return WebGLGetInfo(static_cast<unsigned long>(value));
3085 }
3086
3087 WebGLGetInfo WebGLRenderingContext::getWebGLFloatArrayParameter(unsigned long pname)
3088 {
3089     float value[4] = {0};
3090     m_context->getFloatv(pname, value);
3091     unsigned length = 0;
3092     switch (pname) {
3093     case GraphicsContext3D::ALIASED_POINT_SIZE_RANGE:
3094     case GraphicsContext3D::ALIASED_LINE_WIDTH_RANGE:
3095     case GraphicsContext3D::DEPTH_RANGE:
3096         length = 2;
3097         break;
3098     case GraphicsContext3D::BLEND_COLOR:
3099     case GraphicsContext3D::COLOR_CLEAR_VALUE:
3100         length = 4;
3101         break;
3102     default:
3103         notImplemented();
3104     }
3105     return WebGLGetInfo(Float32Array::create(value, length));
3106 }
3107
3108 WebGLGetInfo WebGLRenderingContext::getWebGLIntArrayParameter(unsigned long pname)
3109 {
3110     int value[4] = {0};
3111     m_context->getIntegerv(pname, value);
3112     unsigned length = 0;
3113     switch (pname) {
3114     case GraphicsContext3D::MAX_VIEWPORT_DIMS:
3115         length = 2;
3116         break;
3117     case GraphicsContext3D::SCISSOR_BOX:
3118     case GraphicsContext3D::VIEWPORT:
3119         length = 4;
3120         break;
3121     default:
3122         notImplemented();
3123     }
3124     return WebGLGetInfo(Int32Array::create(value, length));
3125 }
3126
3127 bool WebGLRenderingContext::isGLES2Compliant()
3128 {
3129     return m_context->isGLES2Compliant();
3130 }
3131
3132 void WebGLRenderingContext::handleNPOTTextures(bool prepareToDraw)
3133 {
3134     if (isGLES2Compliant())
3135         return;
3136     bool resetActiveUnit = false;
3137     for (unsigned ii = 0; ii < m_textureUnits.size(); ++ii) {
3138         if (m_textureUnits[ii].m_texture2DBinding && m_textureUnits[ii].m_texture2DBinding->needToUseBlackTexture()
3139             || m_textureUnits[ii].m_textureCubeMapBinding && m_textureUnits[ii].m_textureCubeMapBinding->needToUseBlackTexture()) {
3140             if (ii != m_activeTextureUnit) {
3141                 m_context->activeTexture(ii);
3142                 resetActiveUnit = true;
3143             } else if (resetActiveUnit) {
3144                 m_context->activeTexture(ii);
3145                 resetActiveUnit = false;
3146             }
3147             WebGLTexture* tex2D;
3148             WebGLTexture* texCubeMap;
3149             if (prepareToDraw) {
3150                 tex2D = m_blackTexture2D.get();
3151                 texCubeMap = m_blackTextureCubeMap.get();
3152             } else {
3153                 tex2D = m_textureUnits[ii].m_texture2DBinding.get();
3154                 texCubeMap = m_textureUnits[ii].m_textureCubeMapBinding.get();
3155             }
3156             if (m_textureUnits[ii].m_texture2DBinding && m_textureUnits[ii].m_texture2DBinding->needToUseBlackTexture())
3157                 m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, tex2D);
3158             if (m_textureUnits[ii].m_textureCubeMapBinding && m_textureUnits[ii].m_textureCubeMapBinding->needToUseBlackTexture())
3159                 m_context->bindTexture(GraphicsContext3D::TEXTURE_CUBE_MAP, texCubeMap);
3160         }
3161     }
3162     if (resetActiveUnit)
3163         m_context->activeTexture(m_activeTextureUnit);
3164 }
3165
3166 void WebGLRenderingContext::createFallbackBlackTextures1x1()
3167 {
3168     unsigned char black[] = {0, 0, 0, 255};
3169     m_blackTexture2D = createTexture();
3170     m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_blackTexture2D.get());
3171     m_context->texImage2D(GraphicsContext3D::TEXTURE_2D, 0, GraphicsContext3D::RGBA, 1, 1,
3172                           0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, black);
3173     m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, 0);
3174     m_blackTextureCubeMap = createTexture();
3175     m_context->bindTexture(GraphicsContext3D::TEXTURE_CUBE_MAP, m_blackTextureCubeMap.get());
3176     m_context->texImage2D(GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_X, 0, GraphicsContext3D::RGBA, 1, 1,
3177                           0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, black);
3178     m_context->texImage2D(GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GraphicsContext3D::RGBA, 1, 1,
3179                           0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, black);
3180     m_context->texImage2D(GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GraphicsContext3D::RGBA, 1, 1,
3181                           0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, black);
3182     m_context->texImage2D(GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GraphicsContext3D::RGBA, 1, 1,
3183                           0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, black);
3184     m_context->texImage2D(GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GraphicsContext3D::RGBA, 1, 1,
3185                           0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, black);
3186     m_context->texImage2D(GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GraphicsContext3D::RGBA, 1, 1,
3187                           0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, black);
3188     m_context->bindTexture(GraphicsContext3D::TEXTURE_CUBE_MAP, 0);
3189 }
3190
3191 bool WebGLRenderingContext::isTexInternalFormatColorBufferCombinationValid(unsigned long texInternalFormat,
3192                                                                            unsigned long colorBufferFormat)
3193 {
3194     switch (colorBufferFormat) {
3195     case GraphicsContext3D::ALPHA:
3196         if (texInternalFormat == GraphicsContext3D::ALPHA)
3197             return true;
3198         break;
3199     case GraphicsContext3D::RGB:
3200         if (texInternalFormat == GraphicsContext3D::LUMINANCE
3201             || texInternalFormat == GraphicsContext3D::RGB)
3202             return true;
3203         break;
3204     case GraphicsContext3D::RGBA:
3205         return true;
3206     }
3207     return false;
3208 }
3209
3210 WebGLTexture* WebGLRenderingContext::getTextureBinding(unsigned long target)
3211 {
3212     RefPtr<WebGLTexture> tex = 0;
3213     switch (target) {
3214     case GraphicsContext3D::TEXTURE_2D:
3215         tex = m_textureUnits[m_activeTextureUnit].m_texture2DBinding;
3216         break;
3217     case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_X:
3218     case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_X:
3219     case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Y:
3220     case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Y:
3221     case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Z:
3222     case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Z:
3223         tex = m_textureUnits[m_activeTextureUnit].m_textureCubeMapBinding;
3224         break;
3225     }
3226     if (tex && tex->object())
3227         return tex.get();
3228     return 0;
3229 }
3230
3231 bool WebGLRenderingContext::validateTexFuncFormatAndType(unsigned long format, unsigned long type)
3232 {
3233     switch (format) {
3234     case GraphicsContext3D::ALPHA:
3235     case GraphicsContext3D::LUMINANCE:
3236     case GraphicsContext3D::LUMINANCE_ALPHA:
3237     case GraphicsContext3D::RGB:
3238     case GraphicsContext3D::RGBA:
3239         break;
3240     default:
3241         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
3242         return false;
3243     }
3244
3245     switch (type) {
3246     case GraphicsContext3D::UNSIGNED_BYTE:
3247     case GraphicsContext3D::UNSIGNED_SHORT_5_6_5:
3248     case GraphicsContext3D::UNSIGNED_SHORT_4_4_4_4:
3249     case GraphicsContext3D::UNSIGNED_SHORT_5_5_5_1:
3250         break;
3251     default:
3252         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
3253         return false;
3254     }
3255
3256     // Verify that the combination of format and type is supported.
3257     switch (format) {
3258     case GraphicsContext3D::ALPHA:
3259     case GraphicsContext3D::LUMINANCE:
3260     case GraphicsContext3D::LUMINANCE_ALPHA:
3261         if (type != GraphicsContext3D::UNSIGNED_BYTE) {
3262             m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
3263             return false;
3264         }
3265         break;
3266     case GraphicsContext3D::RGB:
3267         if (type != GraphicsContext3D::UNSIGNED_BYTE
3268             && type != GraphicsContext3D::UNSIGNED_SHORT_5_6_5) {
3269             m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
3270             return false;
3271         }
3272         break;
3273     case GraphicsContext3D::RGBA:
3274         if (type != GraphicsContext3D::UNSIGNED_BYTE
3275             && type != GraphicsContext3D::UNSIGNED_SHORT_4_4_4_4
3276             && type != GraphicsContext3D::UNSIGNED_SHORT_5_5_5_1) {
3277             m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
3278             return false;
3279         }
3280         break;
3281     default:
3282         ASSERT_NOT_REACHED();
3283     }
3284
3285     return true;
3286 }
3287
3288 bool WebGLRenderingContext::validateTexFuncParameters(unsigned long target, long level,
3289                                                       unsigned long internalformat,
3290                                                       long width, long height, long border,
3291                                                       unsigned long format, unsigned long type)
3292 {
3293     // We absolutely have to validate the format and type combination.
3294     // The texImage2D entry points taking HTMLImage, etc. will produce
3295     // temporary data based on this combination, so it must be legal.
3296     if (!validateTexFuncFormatAndType(format, type))
3297         return false;
3298
3299     if (isGLES2Compliant())
3300         return true;
3301
3302     if (width < 0 || height < 0 || level < 0) {
3303         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
3304         return false;
3305     }
3306
3307     switch (target) {
3308     case GraphicsContext3D::TEXTURE_2D:
3309         if (width > m_maxTextureSize || height > m_maxTextureSize) {
3310             m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
3311             return false;
3312         }
3313         break;
3314     case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_X:
3315     case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_X:
3316     case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Y:
3317     case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Y:
3318     case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Z:
3319     case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Z:
3320         if (width != height || width > m_maxCubeMapTextureSize) {
3321             m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
3322             return false;
3323         }
3324         break;
3325     default:
3326         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
3327         return false;
3328     }
3329
3330     if (format != internalformat) {
3331         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
3332         return false;
3333     }
3334
3335     if (border) {
3336         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
3337         return false;
3338     }
3339
3340     return true;
3341 }
3342
3343 bool WebGLRenderingContext::validateTexFuncData(long width, long height,
3344                                                 unsigned long format, unsigned long type,
3345                                                 ArrayBufferView* pixels)
3346 {
3347     if (!pixels)
3348         return true;
3349
3350     if (!validateTexFuncFormatAndType(format, type))
3351         return false;
3352
3353     switch (type) {
3354     case GraphicsContext3D::UNSIGNED_BYTE:
3355         if (!pixels->isUnsignedByteArray()) {
3356             m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
3357             return false;
3358         }
3359         break;
3360     case GraphicsContext3D::UNSIGNED_SHORT_5_6_5:
3361     case GraphicsContext3D::UNSIGNED_SHORT_4_4_4_4:
3362     case GraphicsContext3D::UNSIGNED_SHORT_5_5_5_1:
3363         if (!pixels->isUnsignedShortArray()) {
3364             m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
3365             return false;
3366         }
3367         break;
3368     default:
3369         ASSERT_NOT_REACHED();
3370     }
3371
3372     unsigned long componentsPerPixel, bytesPerComponent;
3373     if (!m_context->computeFormatAndTypeParameters(format, type, &componentsPerPixel, &bytesPerComponent)) {
3374         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
3375         return false;
3376     }
3377
3378     if (!width || !height)
3379         return true;
3380     unsigned int validRowBytes = width * componentsPerPixel * bytesPerComponent;
3381     unsigned int totalRowBytes = validRowBytes;
3382     unsigned int remainder = validRowBytes % m_unpackAlignment;
3383     if (remainder)
3384         totalRowBytes += (m_unpackAlignment - remainder);
3385     unsigned int totalBytesRequired = (height - 1) * totalRowBytes + validRowBytes;
3386     if (pixels->byteLength() < totalBytesRequired) {
3387         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
3388         return false;
3389     }
3390     return true;
3391 }
3392
3393 bool WebGLRenderingContext::validateDrawMode(unsigned long mode)
3394 {
3395     switch (mode) {
3396     case GraphicsContext3D::POINTS:
3397     case GraphicsContext3D::LINE_STRIP:
3398     case GraphicsContext3D::LINE_LOOP:
3399     case GraphicsContext3D::LINES:
3400     case GraphicsContext3D::TRIANGLE_STRIP:
3401     case GraphicsContext3D::TRIANGLE_FAN:
3402     case GraphicsContext3D::TRIANGLES:
3403         return true;
3404     default:
3405         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
3406         return false;
3407     }
3408 }
3409
3410 void WebGLRenderingContext::printWarningToConsole(const String& message)
3411 {
3412     canvas()->document()->frame()->domWindow()->console()->addMessage(HTMLMessageSource, LogMessageType, WarningMessageLevel,
3413                                                                       message, 0, canvas()->document()->url().string());
3414 }
3415
3416 bool WebGLRenderingContext::validateFramebufferFuncParameters(unsigned long target, unsigned long attachment)
3417 {
3418     if (target != GraphicsContext3D::FRAMEBUFFER) {
3419         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
3420         return false;
3421     }
3422     switch (attachment) {
3423     case GraphicsContext3D::COLOR_ATTACHMENT0:
3424     case GraphicsContext3D::DEPTH_ATTACHMENT:
3425     case GraphicsContext3D::STENCIL_ATTACHMENT:
3426     case GraphicsContext3D::DEPTH_STENCIL_ATTACHMENT:
3427         break;
3428     default:
3429         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
3430         return false;
3431     }
3432     return true;
3433 }
3434
3435 bool WebGLRenderingContext::validateBlendEquation(unsigned long mode)
343