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