c258edc3acf6d2bfec518ede4a2a4cc5a80deebc
[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::LINK_STATUS:
1414     case GraphicsContext3D::VALIDATE_STATUS:
1415         m_context->getProgramiv(program, pname, &value);
1416         return WebGLGetInfo(static_cast<bool>(value));
1417     case GraphicsContext3D::INFO_LOG_LENGTH:
1418     case GraphicsContext3D::ATTACHED_SHADERS:
1419     case GraphicsContext3D::ACTIVE_ATTRIBUTES:
1420     case GraphicsContext3D::ACTIVE_ATTRIBUTE_MAX_LENGTH:
1421     case GraphicsContext3D::ACTIVE_UNIFORMS:
1422     case GraphicsContext3D::ACTIVE_UNIFORM_MAX_LENGTH:
1423         m_context->getProgramiv(program, pname, &value);
1424         return WebGLGetInfo(static_cast<long>(value));
1425     default:
1426         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
1427         return WebGLGetInfo();
1428     }
1429 }
1430
1431 String WebGLRenderingContext::getProgramInfoLog(WebGLProgram* program, ExceptionCode& ec)
1432 {
1433     UNUSED_PARAM(ec);
1434     if (!validateWebGLObject(program))
1435         return "";
1436     WebGLStateRestorer(this, false);
1437     return m_context->getProgramInfoLog(program);
1438 }
1439
1440 WebGLGetInfo WebGLRenderingContext::getRenderbufferParameter(unsigned long target, unsigned long pname, ExceptionCode& ec)
1441 {
1442     UNUSED_PARAM(ec);
1443     if (target != GraphicsContext3D::RENDERBUFFER) {
1444         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
1445         return WebGLGetInfo();
1446     }
1447
1448     WebGLStateRestorer(this, false);
1449     int value = 0;
1450     switch (pname) {
1451     case GraphicsContext3D::RENDERBUFFER_WIDTH:
1452     case GraphicsContext3D::RENDERBUFFER_HEIGHT:
1453     case GraphicsContext3D::RENDERBUFFER_RED_SIZE:
1454     case GraphicsContext3D::RENDERBUFFER_GREEN_SIZE:
1455     case GraphicsContext3D::RENDERBUFFER_BLUE_SIZE:
1456     case GraphicsContext3D::RENDERBUFFER_ALPHA_SIZE:
1457     case GraphicsContext3D::RENDERBUFFER_DEPTH_SIZE:
1458     case GraphicsContext3D::RENDERBUFFER_STENCIL_SIZE:
1459         m_context->getRenderbufferParameteriv(target, pname, &value);
1460         return WebGLGetInfo(static_cast<long>(value));
1461     case GraphicsContext3D::RENDERBUFFER_INTERNAL_FORMAT:
1462         if (!m_renderbufferBinding) {
1463             m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
1464             return WebGLGetInfo();
1465         }
1466         return WebGLGetInfo(m_renderbufferBinding->getInternalFormat());
1467     default:
1468         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
1469         return WebGLGetInfo();
1470     }
1471 }
1472
1473 WebGLGetInfo WebGLRenderingContext::getShaderParameter(WebGLShader* shader, unsigned long pname, ExceptionCode& ec)
1474 {
1475     UNUSED_PARAM(ec);
1476     if (!validateWebGLObject(shader))
1477         return WebGLGetInfo();
1478     WebGLStateRestorer(this, false);
1479     int value = 0;
1480     switch (pname) {
1481     case GraphicsContext3D::DELETE_STATUS:
1482     case GraphicsContext3D::COMPILE_STATUS:
1483         m_context->getShaderiv(shader, pname, &value);
1484         return WebGLGetInfo(static_cast<bool>(value));
1485     case GraphicsContext3D::SHADER_TYPE:
1486         m_context->getShaderiv(shader, pname, &value);
1487         return WebGLGetInfo(static_cast<unsigned long>(value));
1488     case GraphicsContext3D::INFO_LOG_LENGTH:
1489     case GraphicsContext3D::SHADER_SOURCE_LENGTH:
1490         m_context->getShaderiv(shader, pname, &value);
1491         return WebGLGetInfo(static_cast<long>(value));
1492     default:
1493         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
1494         return WebGLGetInfo();
1495     }
1496 }
1497
1498 String WebGLRenderingContext::getShaderInfoLog(WebGLShader* shader, ExceptionCode& ec)
1499 {
1500     UNUSED_PARAM(ec);
1501     if (!validateWebGLObject(shader))
1502         return "";
1503     WebGLStateRestorer(this, false);
1504     return m_context->getShaderInfoLog(shader);
1505 }
1506
1507 String WebGLRenderingContext::getShaderSource(WebGLShader* shader, ExceptionCode& ec)
1508 {
1509     UNUSED_PARAM(ec);
1510     if (!validateWebGLObject(shader))
1511         return "";
1512     WebGLStateRestorer(this, false);
1513     return m_context->getShaderSource(shader);
1514 }
1515
1516 String WebGLRenderingContext::getString(unsigned long name)
1517 {
1518     WebGLStateRestorer(this, false);
1519     return m_context->getString(name);
1520 }
1521
1522 WebGLGetInfo WebGLRenderingContext::getTexParameter(unsigned long target, unsigned long pname, ExceptionCode& ec)
1523 {
1524     UNUSED_PARAM(ec);
1525     if (target != GraphicsContext3D::TEXTURE_2D
1526         && target != GraphicsContext3D::TEXTURE_CUBE_MAP) {
1527         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
1528         return WebGLGetInfo();
1529     }
1530     WebGLStateRestorer(this, false);
1531     int value = 0;
1532     switch (pname) {
1533     case GraphicsContext3D::TEXTURE_MAG_FILTER:
1534     case GraphicsContext3D::TEXTURE_MIN_FILTER:
1535     case GraphicsContext3D::TEXTURE_WRAP_S:
1536     case GraphicsContext3D::TEXTURE_WRAP_T:
1537         m_context->getTexParameteriv(target, pname, &value);
1538         return WebGLGetInfo(static_cast<unsigned long>(value));
1539     default:
1540         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
1541         return WebGLGetInfo();
1542     }
1543 }
1544
1545 WebGLGetInfo WebGLRenderingContext::getUniform(WebGLProgram* program, const WebGLUniformLocation* uniformLocation, ExceptionCode& ec)
1546 {
1547     UNUSED_PARAM(ec);
1548     if (!validateWebGLObject(program))
1549         return WebGLGetInfo();
1550     if (uniformLocation->program() != program) {
1551         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
1552         return WebGLGetInfo();
1553     }
1554     long location = uniformLocation->location();
1555     
1556     WebGLStateRestorer(this, false);
1557     // FIXME: make this more efficient using WebGLUniformLocation and caching types in it
1558     int activeUniforms = 0;
1559     m_context->getProgramiv(program, GraphicsContext3D::ACTIVE_UNIFORMS, &activeUniforms);
1560     for (int i = 0; i < activeUniforms; i++) {
1561         ActiveInfo info;
1562         if (!m_context->getActiveUniform(program, i, info))
1563             return WebGLGetInfo();
1564         // Strip "[0]" from the name if it's an array.
1565         if (info.size > 1)
1566             info.name = info.name.left(info.name.length() - 3);
1567         // If it's an array, we need to iterate through each element, appending "[index]" to the name.
1568         for (int index = 0; index < info.size; ++index) {
1569             String name = info.name;
1570             if (info.size > 1 && index >= 1) {
1571                 name.append('[');
1572                 name.append(String::number(index));
1573                 name.append(']');
1574             }
1575             // Now need to look this up by name again to find its location
1576             long loc = m_context->getUniformLocation(program, name);
1577             if (loc == location) {
1578                 // Found it. Use the type in the ActiveInfo to determine the return type.
1579                 GraphicsContext3D::WebGLEnumType baseType;
1580                 unsigned length;
1581                 switch (info.type) {
1582                 case GraphicsContext3D::BOOL:
1583                     baseType = GraphicsContext3D::BOOL;
1584                     length = 1;
1585                     break;
1586                 case GraphicsContext3D::BOOL_VEC2:
1587                     baseType = GraphicsContext3D::BOOL;
1588                     length = 2;
1589                     break;
1590                 case GraphicsContext3D::BOOL_VEC3:
1591                     baseType = GraphicsContext3D::BOOL;
1592                     length = 3;
1593                     break;
1594                 case GraphicsContext3D::BOOL_VEC4:
1595                     baseType = GraphicsContext3D::BOOL;
1596                     length = 4;
1597                     break;
1598                 case GraphicsContext3D::INT:
1599                     baseType = GraphicsContext3D::INT;
1600                     length = 1;
1601                     break;
1602                 case GraphicsContext3D::INT_VEC2:
1603                     baseType = GraphicsContext3D::INT;
1604                     length = 2;
1605                     break;
1606                 case GraphicsContext3D::INT_VEC3:
1607                     baseType = GraphicsContext3D::INT;
1608                     length = 3;
1609                     break;
1610                 case GraphicsContext3D::INT_VEC4:
1611                     baseType = GraphicsContext3D::INT;
1612                     length = 4;
1613                     break;
1614                 case GraphicsContext3D::FLOAT:
1615                     baseType = GraphicsContext3D::FLOAT;
1616                     length = 1;
1617                     break;
1618                 case GraphicsContext3D::FLOAT_VEC2:
1619                     baseType = GraphicsContext3D::FLOAT;
1620                     length = 2;
1621                     break;
1622                 case GraphicsContext3D::FLOAT_VEC3:
1623                     baseType = GraphicsContext3D::FLOAT;
1624                     length = 3;
1625                     break;
1626                 case GraphicsContext3D::FLOAT_VEC4:
1627                     baseType = GraphicsContext3D::FLOAT;
1628                     length = 4;
1629                     break;
1630                 case GraphicsContext3D::FLOAT_MAT2:
1631                     baseType = GraphicsContext3D::FLOAT;
1632                     length = 4;
1633                     break;
1634                 case GraphicsContext3D::FLOAT_MAT3:
1635                     baseType = GraphicsContext3D::FLOAT;
1636                     length = 9;
1637                     break;
1638                 case GraphicsContext3D::FLOAT_MAT4:
1639                     baseType = GraphicsContext3D::FLOAT;
1640                     length = 16;
1641                     break;
1642                 default:
1643                     // Can't handle this type
1644                     // FIXME: what to do about samplers?
1645                     m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
1646                     return WebGLGetInfo();
1647                 }
1648                 switch (baseType) {
1649                 case GraphicsContext3D::FLOAT: {
1650                     float value[16] = {0};
1651                     m_context->getUniformfv(program, location, value);
1652                     if (length == 1)
1653                         return WebGLGetInfo(value[0]);
1654                     return WebGLGetInfo(Float32Array::create(value, length));
1655                 }
1656                 case GraphicsContext3D::INT: {
1657                     int value[16] = {0};
1658                     m_context->getUniformiv(program, location, value);
1659                     if (length == 1)
1660                         return WebGLGetInfo(static_cast<long>(value[0]));
1661                     return WebGLGetInfo(Int32Array::create(value, length));
1662                 }
1663                 case GraphicsContext3D::BOOL: {
1664                     int value[16] = {0};
1665                     m_context->getUniformiv(program, location, value);
1666                     if (length > 1) {
1667                         unsigned char boolValue[16] = {0};
1668                         for (unsigned j = 0; j < length; j++)
1669                             boolValue[j] = static_cast<bool>(value[j]);
1670                         return WebGLGetInfo(Uint8Array::create(boolValue, length));
1671                     }
1672                     return WebGLGetInfo(static_cast<bool>(value[0]));
1673                 }
1674                 default:
1675                     notImplemented();
1676                 }
1677             }
1678         }
1679     }
1680     // If we get here, something went wrong in our unfortunately complex logic above
1681     m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
1682     return WebGLGetInfo();
1683 }
1684
1685 PassRefPtr<WebGLUniformLocation> WebGLRenderingContext::getUniformLocation(WebGLProgram* program, const String& name, ExceptionCode& ec)
1686 {
1687     UNUSED_PARAM(ec);
1688     if (!validateWebGLObject(program))
1689         return 0;
1690     WebGLStateRestorer(this, false);
1691     long uniformLocation = m_context->getUniformLocation(program, name);
1692     if (uniformLocation == -1)
1693         return 0;
1694     return WebGLUniformLocation::create(program, uniformLocation);
1695 }
1696
1697 WebGLGetInfo WebGLRenderingContext::getVertexAttrib(unsigned long index, unsigned long pname, ExceptionCode& ec)
1698 {
1699     UNUSED_PARAM(ec);
1700     WebGLStateRestorer(this, false);
1701     if (index >= m_maxVertexAttribs) {
1702         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
1703         return WebGLGetInfo();
1704     }
1705     switch (pname) {
1706     case GraphicsContext3D::VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
1707         if (!isGLES2Compliant() && !index && m_vertexAttribState[0].bufferBinding == m_vertexAttrib0Buffer
1708             || index >= m_vertexAttribState.size()
1709             || !m_vertexAttribState[index].bufferBinding
1710             || !m_vertexAttribState[index].bufferBinding->object())
1711             return WebGLGetInfo();
1712         return WebGLGetInfo(PassRefPtr<WebGLBuffer>(m_vertexAttribState[index].bufferBinding));
1713     case GraphicsContext3D::VERTEX_ATTRIB_ARRAY_ENABLED:
1714         if (index >= m_vertexAttribState.size())
1715             return WebGLGetInfo(false);
1716         return WebGLGetInfo(m_vertexAttribState[index].enabled);
1717     case GraphicsContext3D::VERTEX_ATTRIB_ARRAY_NORMALIZED:
1718         if (index >= m_vertexAttribState.size())
1719             return WebGLGetInfo(false);
1720         return WebGLGetInfo(m_vertexAttribState[index].normalized);
1721     case GraphicsContext3D::VERTEX_ATTRIB_ARRAY_SIZE:
1722         if (index >= m_vertexAttribState.size())
1723             return WebGLGetInfo(static_cast<long>(4));
1724         return WebGLGetInfo(m_vertexAttribState[index].size);
1725     case GraphicsContext3D::VERTEX_ATTRIB_ARRAY_STRIDE:
1726         if (index >= m_vertexAttribState.size())
1727             return WebGLGetInfo(static_cast<long>(0));
1728         return WebGLGetInfo(m_vertexAttribState[index].originalStride);
1729     case GraphicsContext3D::VERTEX_ATTRIB_ARRAY_TYPE:
1730         if (index >= m_vertexAttribState.size())
1731             return WebGLGetInfo(static_cast<unsigned long>(GraphicsContext3D::FLOAT));
1732         return WebGLGetInfo(m_vertexAttribState[index].type);
1733     case GraphicsContext3D::CURRENT_VERTEX_ATTRIB:
1734         if (index >= m_vertexAttribState.size()) {
1735             float value[4] = { 0.0f, 0.0f, 0.0f, 1.0f };
1736             return WebGLGetInfo(Float32Array::create(value, 4));
1737         }
1738         return WebGLGetInfo(Float32Array::create(m_vertexAttribState[index].value, 4));
1739     default:
1740         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
1741         return WebGLGetInfo();
1742     }
1743 }
1744
1745 long WebGLRenderingContext::getVertexAttribOffset(unsigned long index, unsigned long pname)
1746 {
1747     long result = m_context->getVertexAttribOffset(index, pname);
1748     cleanupAfterGraphicsCall(false);
1749     return result;
1750 }
1751
1752 void WebGLRenderingContext::hint(unsigned long target, unsigned long mode)
1753 {
1754     if (!isGLES2Compliant()) {
1755         if (target != GraphicsContext3D::GENERATE_MIPMAP_HINT) {
1756             m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
1757             return;
1758         }
1759     }
1760     m_context->hint(target, mode);
1761     cleanupAfterGraphicsCall(false);
1762 }
1763
1764 bool WebGLRenderingContext::isBuffer(WebGLBuffer* buffer)
1765 {
1766     if (!buffer)
1767         return false;
1768
1769     return m_context->isBuffer(buffer);
1770 }
1771
1772 bool WebGLRenderingContext::isEnabled(unsigned long cap)
1773 {
1774     if (!isGLES2Compliant()) {
1775         if (!validateCapability(cap))
1776             return false;
1777     }
1778     return m_context->isEnabled(cap);
1779 }
1780
1781 bool WebGLRenderingContext::isFramebuffer(WebGLFramebuffer* framebuffer)
1782 {
1783     if (!framebuffer)
1784         return false;
1785
1786     return m_context->isFramebuffer(framebuffer);
1787 }
1788
1789 bool WebGLRenderingContext::isProgram(WebGLProgram* program)
1790 {
1791     if (!program)
1792         return false;
1793
1794     return m_context->isProgram(program);
1795 }
1796
1797 bool WebGLRenderingContext::isRenderbuffer(WebGLRenderbuffer* renderbuffer)
1798 {
1799     if (!renderbuffer)
1800         return false;
1801
1802     return m_context->isRenderbuffer(renderbuffer);
1803 }
1804
1805 bool WebGLRenderingContext::isShader(WebGLShader* shader)
1806 {
1807     if (!shader)
1808         return false;
1809
1810     return m_context->isShader(shader);
1811 }
1812
1813 bool WebGLRenderingContext::isTexture(WebGLTexture* texture)
1814 {
1815     if (!texture)
1816         return false;
1817
1818     return m_context->isTexture(texture);
1819 }
1820
1821 void WebGLRenderingContext::lineWidth(double width)
1822 {
1823     m_context->lineWidth((float) width);
1824     cleanupAfterGraphicsCall(false);
1825 }
1826
1827 void WebGLRenderingContext::linkProgram(WebGLProgram* program, ExceptionCode& ec)
1828 {
1829     UNUSED_PARAM(ec);
1830     if (!validateWebGLObject(program))
1831         return;
1832     m_context->linkProgram(program);
1833     program->cacheActiveAttribLocations();
1834     cleanupAfterGraphicsCall(false);
1835 }
1836
1837 void WebGLRenderingContext::pixelStorei(unsigned long pname, long param)
1838 {
1839     switch (pname) {
1840     case GraphicsContext3D::UNPACK_FLIP_Y_WEBGL:
1841         m_unpackFlipY = param;
1842         break;
1843     case GraphicsContext3D::UNPACK_PREMULTIPLY_ALPHA_WEBGL:
1844         m_unpackPremultiplyAlpha = param;
1845         break;
1846     case GraphicsContext3D::PACK_ALIGNMENT:
1847     case GraphicsContext3D::UNPACK_ALIGNMENT:
1848         m_context->pixelStorei(pname, param);
1849         if (param == 1 || param == 2 || param == 4 || param == 8) {
1850             if (pname == GraphicsContext3D::PACK_ALIGNMENT)
1851                 m_packAlignment = static_cast<int>(param);
1852             else // GraphicsContext3D::UNPACK_ALIGNMENT:
1853                 m_unpackAlignment = static_cast<int>(param);
1854         }
1855         break;
1856     default:
1857         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
1858         return;
1859     }
1860     cleanupAfterGraphicsCall(false);
1861 }
1862
1863 void WebGLRenderingContext::polygonOffset(double factor, double units)
1864 {
1865     m_context->polygonOffset((float) factor, (float) units);
1866     cleanupAfterGraphicsCall(false);
1867 }
1868
1869 void WebGLRenderingContext::readPixels(long x, long y, long width, long height, unsigned long format, unsigned long type, ArrayBufferView* pixels)
1870 {
1871     // Validate input parameters.
1872     unsigned long componentsPerPixel, bytesPerComponent;
1873     if (!m_context->computeFormatAndTypeParameters(format, type, &componentsPerPixel, &bytesPerComponent)) {
1874         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
1875         return;
1876     }
1877     if (!pixels) {
1878         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
1879         return;
1880     }
1881     if (width < 0 || height < 0) {
1882         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
1883         return;
1884     }
1885     if (!((format == GraphicsContext3D::RGBA && type == GraphicsContext3D::UNSIGNED_BYTE) || (format == m_implementationColorReadFormat && type == m_implementationColorReadType))) {
1886         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
1887         return;
1888     }
1889     // Validate array type against pixel type.
1890     if (type == GraphicsContext3D::UNSIGNED_BYTE && !pixels->isUnsignedByteArray()
1891         || type != GraphicsContext3D::UNSIGNED_BYTE && !pixels->isUnsignedShortArray()) {
1892         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
1893         return;
1894     }
1895     // Calculate array size, taking into consideration of PACK_ALIGNMENT.
1896     unsigned long bytesPerRow = componentsPerPixel * bytesPerComponent * width;
1897     unsigned long padding = 0;
1898     unsigned long residualBytes = bytesPerRow % m_packAlignment;
1899     if (residualBytes) {
1900         padding = m_packAlignment - residualBytes;
1901         bytesPerRow += padding;
1902     }
1903     // The last row needs no padding.
1904     unsigned long totalBytes = bytesPerRow * height - padding;
1905     unsigned long num = totalBytes / bytesPerComponent;
1906     if (pixels->length() < num) {
1907         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
1908         return;
1909     }
1910     void* data = pixels->baseAddress();
1911     m_context->readPixels(x, y, width, height, format, type, data);
1912 #if PLATFORM(CG)
1913     // FIXME: remove this section when GL driver bug on Mac is fixed, i.e.,
1914     // when alpha is off, readPixels should set alpha to 255 instead of 0.
1915     if ((format == GraphicsContext3D::ALPHA || format == GraphicsContext3D::RGBA) && !m_context->getContextAttributes().alpha) {
1916         if (type == GraphicsContext3D::UNSIGNED_BYTE) {
1917             unsigned char* pixels = reinterpret_cast<unsigned char*>(data);
1918             for (long iy = 0; iy < height; ++iy) {
1919                 for (long ix = 0; ix < width; ++ix) {
1920                     pixels[componentsPerPixel - 1] = 255;
1921                     pixels += componentsPerPixel;
1922                 }
1923                 pixels += padding;
1924             }
1925         }
1926         // FIXME: check whether we need to do the same with UNSIGNED_SHORT.
1927     }
1928 #endif
1929     cleanupAfterGraphicsCall(false);
1930 }
1931
1932 void WebGLRenderingContext::releaseShaderCompiler()
1933 {
1934     m_context->releaseShaderCompiler();
1935     cleanupAfterGraphicsCall(false);
1936 }
1937
1938 void WebGLRenderingContext::renderbufferStorage(unsigned long target, unsigned long internalformat, unsigned long width, unsigned long height)
1939 {
1940     switch (internalformat) {
1941     case GraphicsContext3D::DEPTH_COMPONENT16:
1942     case GraphicsContext3D::RGBA4:
1943     case GraphicsContext3D::RGB5_A1:
1944     case GraphicsContext3D::RGB565:
1945     case GraphicsContext3D::STENCIL_INDEX8:
1946     case GraphicsContext3D::DEPTH_STENCIL:
1947         m_context->renderbufferStorage(target, internalformat, width, height);
1948         if (m_renderbufferBinding) {
1949             m_renderbufferBinding->setInternalFormat(internalformat);
1950             if (m_framebufferBinding)
1951                 m_framebufferBinding->onAttachedObjectChange(m_renderbufferBinding.get());
1952         }
1953         cleanupAfterGraphicsCall(false);
1954         break;
1955     default:
1956         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
1957     }
1958 }
1959
1960 void WebGLRenderingContext::sampleCoverage(double value, bool invert)
1961 {
1962     m_context->sampleCoverage((float) value, invert);
1963     cleanupAfterGraphicsCall(false);
1964 }
1965
1966 void WebGLRenderingContext::scissor(long x, long y, unsigned long width, unsigned long height)
1967 {
1968     m_context->scissor(x, y, width, height);
1969     cleanupAfterGraphicsCall(false);
1970 }
1971
1972 void WebGLRenderingContext::shaderSource(WebGLShader* shader, const String& string, ExceptionCode& ec)
1973 {
1974     UNUSED_PARAM(ec);
1975     if (!validateWebGLObject(shader))
1976         return;
1977     m_context->shaderSource(shader, string);
1978     cleanupAfterGraphicsCall(false);
1979 }
1980
1981 void WebGLRenderingContext::stencilFunc(unsigned long func, long ref, unsigned long mask)
1982 {
1983     m_context->stencilFunc(func, ref, mask);
1984     cleanupAfterGraphicsCall(false);
1985 }
1986
1987 void WebGLRenderingContext::stencilFuncSeparate(unsigned long face, unsigned long func, long ref, unsigned long mask)
1988 {
1989     m_context->stencilFuncSeparate(face, func, ref, mask);
1990     cleanupAfterGraphicsCall(false);
1991 }
1992
1993 void WebGLRenderingContext::stencilMask(unsigned long mask)
1994 {
1995     m_context->stencilMask(mask);
1996     cleanupAfterGraphicsCall(false);
1997 }
1998
1999 void WebGLRenderingContext::stencilMaskSeparate(unsigned long face, unsigned long mask)
2000 {
2001     m_context->stencilMaskSeparate(face, mask);
2002     cleanupAfterGraphicsCall(false);
2003 }
2004
2005 void WebGLRenderingContext::stencilOp(unsigned long fail, unsigned long zfail, unsigned long zpass)
2006 {
2007     m_context->stencilOp(fail, zfail, zpass);
2008     cleanupAfterGraphicsCall(false);
2009 }
2010
2011 void WebGLRenderingContext::stencilOpSeparate(unsigned long face, unsigned long fail, unsigned long zfail, unsigned long zpass)
2012 {
2013     m_context->stencilOpSeparate(face, fail, zfail, zpass);
2014     cleanupAfterGraphicsCall(false);
2015 }
2016
2017 void WebGLRenderingContext::texImage2DBase(unsigned target, unsigned level, unsigned internalformat,
2018                                            unsigned width, unsigned height, unsigned border,
2019                                            unsigned format, unsigned type, void* pixels, ExceptionCode& ec)
2020 {
2021     // FIXME: For now we ignore any errors returned
2022     ec = 0;
2023     if (!validateTexFuncParameters(target, level, internalformat, width, height, border, format, type))
2024         return;
2025     if (!isGLES2Compliant()) {
2026         if (level && WebGLTexture::isNPOT(width, height)) {
2027             m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
2028             return;
2029         }
2030     }
2031     m_context->texImage2D(target, level, internalformat, width, height,
2032                           border, format, type, pixels);
2033     WebGLTexture* tex = getTextureBinding(target);
2034     if (!isGLES2Compliant()) {
2035         if (tex && !level) // only for level 0
2036             tex->setSize(target, width, height);
2037         if (tex)
2038             tex->setInternalFormat(internalformat);
2039     }
2040     if (m_framebufferBinding && tex)
2041         m_framebufferBinding->onAttachedObjectChange(tex);
2042     cleanupAfterGraphicsCall(false);
2043 }
2044
2045 void WebGLRenderingContext::texImage2DImpl(unsigned target, unsigned level, unsigned internalformat,
2046                                            unsigned format, unsigned type, Image* image,
2047                                            bool flipY, bool premultiplyAlpha, ExceptionCode& ec)
2048 {
2049     ec = 0;
2050     Vector<uint8_t> data;
2051     if (!m_context->extractImageData(image, format, type, flipY, premultiplyAlpha, data)) {
2052         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
2053         return;
2054     }
2055     if (m_unpackAlignment != 1)
2056         m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, 1);
2057     texImage2DBase(target, level, internalformat, image->width(), image->height(), 0,
2058                    format, type, data.data(), ec);
2059     if (m_unpackAlignment != 1)
2060         m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, m_unpackAlignment);
2061 }
2062
2063 void WebGLRenderingContext::texImage2D(unsigned target, unsigned level, unsigned internalformat,
2064                                        unsigned width, unsigned height, unsigned border,
2065                                        unsigned format, unsigned type, ArrayBufferView* pixels, ExceptionCode& ec)
2066 {
2067     if (!validateTexFuncData(width, height, format, type, pixels))
2068         return;
2069     void* data = pixels ? pixels->baseAddress() : 0;
2070     Vector<uint8_t> tempData;
2071     bool changeUnpackAlignment = false;
2072     if (pixels && (m_unpackFlipY || m_unpackPremultiplyAlpha)) {
2073         if (!m_context->extractTextureData(width, height, format, type,
2074                                            m_unpackAlignment,
2075                                            m_unpackFlipY, m_unpackPremultiplyAlpha,
2076                                            pixels,
2077                                            tempData))
2078             return;
2079         data = tempData.data();
2080         changeUnpackAlignment = true;
2081     }
2082     if (changeUnpackAlignment)
2083         m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, 1);
2084     texImage2DBase(target, level, internalformat, width, height, border,
2085                    format, type, data, ec);
2086     if (changeUnpackAlignment)
2087         m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, m_unpackAlignment);
2088 }
2089
2090 void WebGLRenderingContext::texImage2D(unsigned target, unsigned level, unsigned internalformat,
2091                                        unsigned format, unsigned type, ImageData* pixels, ExceptionCode& ec)
2092 {
2093     ec = 0;
2094     Vector<uint8_t> data;
2095     if (!m_context->extractImageData(pixels, format, type, m_unpackFlipY, m_unpackPremultiplyAlpha, data)) {
2096         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
2097         return;
2098     }
2099     if (m_unpackAlignment != 1)
2100         m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, 1);
2101     texImage2DBase(target, level, internalformat, pixels->width(), pixels->height(), 0,
2102                    format, type, data.data(), ec);
2103     if (m_unpackAlignment != 1)
2104         m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, m_unpackAlignment);
2105 }
2106
2107 void WebGLRenderingContext::texImage2D(unsigned target, unsigned level, unsigned internalformat,
2108                                        unsigned format, unsigned type, HTMLImageElement* image, ExceptionCode& ec)
2109 {
2110     ec = 0;
2111     if (!image || !image->cachedImage()) {
2112         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
2113         return;
2114     }
2115     texImage2DImpl(target, level, internalformat, format, type, image->cachedImage()->image(),
2116                    m_unpackFlipY, m_unpackPremultiplyAlpha, ec);
2117 }
2118
2119 void WebGLRenderingContext::texImage2D(unsigned target, unsigned level, unsigned internalformat,
2120                                        unsigned format, unsigned type, HTMLCanvasElement* canvas, ExceptionCode& ec)
2121 {
2122     ec = 0;
2123     if (!canvas || !canvas->buffer()) {
2124         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
2125         return;
2126     }
2127     texImage2DImpl(target, level, internalformat, format, type, canvas->buffer()->image(),
2128                    m_unpackFlipY, m_unpackPremultiplyAlpha, ec);
2129 }
2130
2131 void WebGLRenderingContext::texImage2D(unsigned target, unsigned level, unsigned internalformat,
2132                                        unsigned format, unsigned type, HTMLVideoElement* video, ExceptionCode& ec)
2133 {
2134     // FIXME: Need to implement this call
2135     UNUSED_PARAM(target);
2136     UNUSED_PARAM(level);
2137     UNUSED_PARAM(internalformat);
2138     UNUSED_PARAM(format);
2139     UNUSED_PARAM(type);
2140     UNUSED_PARAM(video);
2141
2142     ec = 0;
2143     cleanupAfterGraphicsCall(false);
2144 }
2145
2146 // Obsolete texImage2D entry points -- to be removed shortly. (FIXME)
2147
2148 void WebGLRenderingContext::texImage2D(unsigned target, unsigned level, ImageData* pixels,
2149                                        ExceptionCode& ec)
2150 {
2151     printWarningToConsole("Calling obsolete texImage2D(GLenum target, GLint level, ImageData pixels)");
2152     texImage2D(target, level, pixels, 0, 0, ec);
2153 }
2154
2155 void WebGLRenderingContext::texImage2D(unsigned target, unsigned level, ImageData* pixels,
2156                                        bool flipY, ExceptionCode& ec)
2157 {
2158     printWarningToConsole("Calling obsolete texImage2D(GLenum target, GLint level, ImageData pixels, GLboolean flipY)");
2159     texImage2D(target, level, pixels, flipY, 0, ec);
2160 }
2161
2162 void WebGLRenderingContext::texImage2D(unsigned target, unsigned level, ImageData* pixels,
2163                                        bool flipY, bool premultiplyAlpha, ExceptionCode& ec)
2164 {
2165     printWarningToConsole("Calling obsolete texImage2D(GLenum target, GLint level, ImageData pixels, GLboolean flipY, GLboolean premultiplyAlpha)");
2166     ec = 0;
2167     Vector<uint8_t> data;
2168     if (!m_context->extractImageData(pixels, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, flipY, premultiplyAlpha, data)) {
2169         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
2170         return;
2171     }
2172     texImage2DBase(target, level, GraphicsContext3D::RGBA, pixels->width(), pixels->height(), 0,
2173                    GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, data.data(), ec);
2174 }
2175
2176
2177 void WebGLRenderingContext::texImage2D(unsigned target, unsigned level, HTMLImageElement* image,
2178                                        ExceptionCode& ec)
2179 {
2180     printWarningToConsole("Calling obsolete texImage2D(GLenum target, GLint level, HTMLImageElement image)");
2181     texImage2D(target, level, image, 0, 0, ec);
2182 }
2183
2184 void WebGLRenderingContext::texImage2D(unsigned target, unsigned level, HTMLImageElement* image,
2185                                        bool flipY, ExceptionCode& ec)
2186 {
2187     printWarningToConsole("Calling obsolete texImage2D(GLenum target, GLint level, HTMLImageElement image, GLboolean flipY)");
2188     texImage2D(target, level, image, flipY, 0, ec);
2189 }
2190
2191 void WebGLRenderingContext::texImage2D(unsigned target, unsigned level, HTMLImageElement* image,
2192                                        bool flipY, bool premultiplyAlpha, ExceptionCode& ec)
2193 {
2194     printWarningToConsole("Calling obsolete texImage2D(GLenum target, GLint level, HTMLImageElement image, GLboolean flipY, GLboolean premultiplyAlpha)");
2195     ec = 0;
2196     if (!image || !image->cachedImage()) {
2197         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
2198         return;
2199     }
2200     texImage2DImpl(target, level, GraphicsContext3D::RGBA, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, image->cachedImage()->image(), flipY, premultiplyAlpha, ec);
2201 }
2202
2203 void WebGLRenderingContext::texImage2D(unsigned target, unsigned level, HTMLCanvasElement* canvas,
2204                                        ExceptionCode& ec)
2205 {
2206     printWarningToConsole("Calling obsolete texImage2D(GLenum target, GLint level, HTMLCanvasElement canvas)");
2207     texImage2D(target, level, canvas, 0, 0, ec);
2208 }
2209
2210 void WebGLRenderingContext::texImage2D(unsigned target, unsigned level, HTMLCanvasElement* canvas,
2211                                        bool flipY, ExceptionCode& ec)
2212 {
2213     printWarningToConsole("Calling obsolete texImage2D(GLenum target, GLint level, HTMLCanvasElement canvas, GLboolean flipY)");
2214     texImage2D(target, level, canvas, flipY, 0, ec);
2215 }
2216
2217 void WebGLRenderingContext::texImage2D(unsigned target, unsigned level, HTMLCanvasElement* canvas,
2218                                        bool flipY, bool premultiplyAlpha, ExceptionCode& ec)
2219 {
2220     printWarningToConsole("Calling obsolete texImage2D(GLenum target, GLint level, HTMLCanvasElement canvas, GLboolean flipY, GLboolean premultiplyAlpha)");
2221     ec = 0;
2222     if (!canvas || !canvas->buffer()) {
2223         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
2224         return;
2225     }
2226     texImage2DImpl(target, level, GraphicsContext3D::RGBA, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, canvas->buffer()->image(), flipY, premultiplyAlpha, ec);
2227 }
2228
2229 void WebGLRenderingContext::texImage2D(unsigned target, unsigned level, HTMLVideoElement* video,
2230                                        ExceptionCode& ec)
2231 {
2232     texImage2D(target, level, video, 0, 0, ec);
2233 }
2234
2235 void WebGLRenderingContext::texImage2D(unsigned target, unsigned level, HTMLVideoElement* video,
2236                                        bool flipY, ExceptionCode& ec)
2237 {
2238     texImage2D(target, level, video, flipY, 0, ec);
2239 }
2240
2241 void WebGLRenderingContext::texImage2D(unsigned target, unsigned level, HTMLVideoElement* video,
2242                                        bool flipY, bool premultiplyAlpha, ExceptionCode& ec)
2243 {
2244     // FIXME: Need implement this call
2245     UNUSED_PARAM(target);
2246     UNUSED_PARAM(level);
2247     UNUSED_PARAM(video);
2248     UNUSED_PARAM(flipY);
2249     UNUSED_PARAM(premultiplyAlpha);
2250     
2251     ec = 0;
2252     cleanupAfterGraphicsCall(false);
2253 }
2254
2255 void WebGLRenderingContext::texParameter(unsigned long target, unsigned long pname, float paramf, int parami, bool isFloat)
2256 {
2257     if (!isGLES2Compliant()) {
2258         RefPtr<WebGLTexture> tex = 0;
2259         switch (target) {
2260         case GraphicsContext3D::TEXTURE_2D:
2261             tex = m_textureUnits[m_activeTextureUnit].m_texture2DBinding;
2262             break;
2263         case GraphicsContext3D::TEXTURE_CUBE_MAP:
2264             tex = m_textureUnits[m_activeTextureUnit].m_textureCubeMapBinding;
2265             break;
2266         default:
2267             m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
2268             return;
2269         }
2270         switch (pname) {
2271         case GraphicsContext3D::TEXTURE_MIN_FILTER:
2272         case GraphicsContext3D::TEXTURE_MAG_FILTER:
2273             break;
2274         case GraphicsContext3D::TEXTURE_WRAP_S:
2275         case GraphicsContext3D::TEXTURE_WRAP_T:
2276             if (isFloat && paramf != GraphicsContext3D::CLAMP_TO_EDGE && paramf != GraphicsContext3D::MIRRORED_REPEAT && paramf != GraphicsContext3D::REPEAT
2277                 || !isFloat && parami != GraphicsContext3D::CLAMP_TO_EDGE && parami != GraphicsContext3D::MIRRORED_REPEAT && parami != GraphicsContext3D::REPEAT) {
2278                 m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
2279                 return;
2280             }
2281             break;
2282         default:
2283             m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
2284             return;
2285         }
2286         if (tex) {
2287             if (isFloat)
2288                 tex->setParameterf(pname, paramf);
2289             else
2290                 tex->setParameteri(pname, parami);
2291         }
2292     }
2293     if (isFloat)
2294         m_context->texParameterf(target, pname, paramf);
2295     else
2296         m_context->texParameteri(target, pname, parami);
2297     cleanupAfterGraphicsCall(false);
2298 }
2299
2300 void WebGLRenderingContext::texParameterf(unsigned target, unsigned pname, float param)
2301 {
2302     texParameter(target, pname, param, 0, true);
2303 }
2304
2305 void WebGLRenderingContext::texParameteri(unsigned target, unsigned pname, int param)
2306 {
2307     texParameter(target, pname, 0, param, false);
2308 }
2309
2310 void WebGLRenderingContext::texSubImage2DBase(unsigned target, unsigned level, unsigned xoffset, unsigned yoffset,
2311                                               unsigned width, unsigned height,
2312                                               unsigned format, unsigned type, void* pixels, ExceptionCode& ec)
2313 {
2314     // FIXME: For now we ignore any errors returned
2315     ec = 0;
2316     if (!validateTexFuncFormatAndType(format, type))
2317         return;
2318
2319     m_context->texSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels);
2320     cleanupAfterGraphicsCall(false);
2321 }
2322
2323 void WebGLRenderingContext::texSubImage2DImpl(unsigned target, unsigned level, unsigned xoffset, unsigned yoffset,
2324                                               unsigned format, unsigned type,
2325                                               Image* image, bool flipY, bool premultiplyAlpha, ExceptionCode& ec)
2326 {
2327     ec = 0;
2328     Vector<uint8_t> data;
2329     if (!m_context->extractImageData(image, format, type, flipY, premultiplyAlpha, data)) {
2330         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
2331         return;
2332     }
2333     texSubImage2DBase(target, level, xoffset, yoffset, image->width(), image->height(),
2334                       format, type, data.data(), ec);
2335 }
2336
2337 void WebGLRenderingContext::texSubImage2D(unsigned target, unsigned level, unsigned xoffset, unsigned yoffset,
2338                                           unsigned width, unsigned height,
2339                                           unsigned format, unsigned type, ArrayBufferView* pixels, ExceptionCode& ec)
2340 {
2341     if (!validateTexFuncData(width, height, format, type, pixels))
2342         return;
2343     void* data = pixels ? pixels->baseAddress() : 0;
2344     Vector<uint8_t> tempData;
2345     bool changeUnpackAlignment = false;
2346     if (pixels && (m_unpackFlipY || m_unpackPremultiplyAlpha)) {
2347         if (!m_context->extractTextureData(width, height, format, type,
2348                                            m_unpackAlignment,
2349                                            m_unpackFlipY, m_unpackPremultiplyAlpha,
2350                                            pixels,
2351                                            tempData))
2352             return;
2353         data = tempData.data();
2354         changeUnpackAlignment = true;
2355     }
2356     if (changeUnpackAlignment)
2357         m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, 1);
2358     texSubImage2DBase(target, level, xoffset, yoffset, width, height, format, type, data, ec);
2359     if (changeUnpackAlignment)
2360         m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, m_unpackAlignment);
2361 }
2362
2363 void WebGLRenderingContext::texSubImage2D(unsigned target, unsigned level, unsigned xoffset, unsigned yoffset,
2364                                           unsigned format, unsigned type, ImageData* pixels, ExceptionCode& ec)
2365 {
2366     ec = 0;
2367     Vector<uint8_t> data;
2368     if (!m_context->extractImageData(pixels, format, type, m_unpackFlipY, m_unpackPremultiplyAlpha, data)) {
2369         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
2370         return;
2371     }
2372     texSubImage2DBase(target, level, xoffset, yoffset, pixels->width(), pixels->height(),
2373                       format, type, data.data(), ec);
2374 }
2375
2376 void WebGLRenderingContext::texSubImage2D(unsigned target, unsigned level, unsigned xoffset, unsigned yoffset,
2377                                           unsigned format, unsigned type, HTMLImageElement* image, ExceptionCode& ec)
2378 {
2379     ec = 0;
2380     if (!image || !image->cachedImage()) {
2381         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
2382         return;
2383     }
2384     texSubImage2DImpl(target, level, xoffset, yoffset, format, type, image->cachedImage()->image(),
2385                       m_unpackFlipY, m_unpackPremultiplyAlpha, ec);
2386 }
2387
2388 void WebGLRenderingContext::texSubImage2D(unsigned target, unsigned level, unsigned xoffset, unsigned yoffset,
2389                                           unsigned format, unsigned type, HTMLCanvasElement* canvas, ExceptionCode& ec)
2390 {
2391     ec = 0;
2392     if (!canvas || !canvas->buffer()) {
2393         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
2394         return;
2395     }
2396     texSubImage2DImpl(target, level, xoffset, yoffset, format, type, canvas->buffer()->image(),
2397                       m_unpackFlipY, m_unpackPremultiplyAlpha, ec);
2398 }
2399
2400 void WebGLRenderingContext::texSubImage2D(unsigned target, unsigned level, unsigned xoffset, unsigned yoffset,
2401                                           unsigned format, unsigned type, HTMLVideoElement* video, ExceptionCode& ec)
2402 {
2403     // FIXME: Need to implement this call
2404     UNUSED_PARAM(target);
2405     UNUSED_PARAM(level);
2406     UNUSED_PARAM(xoffset);
2407     UNUSED_PARAM(yoffset);
2408     UNUSED_PARAM(format);
2409     UNUSED_PARAM(type);
2410     UNUSED_PARAM(video);
2411     ec = 0;
2412     cleanupAfterGraphicsCall(false);
2413 }
2414
2415 // Obsolete texSubImage2D entry points -- to be removed shortly. (FIXME)
2416
2417 void WebGLRenderingContext::texSubImage2D(unsigned target, unsigned level, unsigned xoffset, unsigned yoffset,
2418                                           ImageData* pixels, ExceptionCode& ec)
2419 {
2420     printWarningToConsole("Calling obsolete texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, ImageData pixels)");
2421     texSubImage2D(target, level, xoffset, yoffset, pixels, 0, 0, ec);
2422 }
2423
2424 void WebGLRenderingContext::texSubImage2D(unsigned target, unsigned level, unsigned xoffset, unsigned yoffset,
2425                                           ImageData* pixels, bool flipY, ExceptionCode& ec)
2426 {
2427     printWarningToConsole("Calling obsolete texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, ImageData pixels, GLboolean flipY)");
2428     texSubImage2D(target, level, xoffset, yoffset, pixels, flipY, 0, ec);
2429 }
2430
2431 void WebGLRenderingContext::texSubImage2D(unsigned target, unsigned level, unsigned xoffset, unsigned yoffset,
2432                                           ImageData* pixels, bool flipY, bool premultiplyAlpha, ExceptionCode& ec)
2433 {
2434     printWarningToConsole("Calling obsolete texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, ImageData pixels, GLboolean flipY, GLboolean premultiplyAlpha)");
2435     ec = 0;
2436     Vector<uint8_t> data;
2437     if (!m_context->extractImageData(pixels, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, flipY, premultiplyAlpha, data)) {
2438         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
2439         return;
2440     }
2441     texSubImage2DBase(target, level, xoffset, yoffset, pixels->width(), pixels->height(),
2442                       GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, data.data(), ec);
2443 }
2444
2445 void WebGLRenderingContext::texSubImage2D(unsigned target, unsigned level, unsigned xoffset, unsigned yoffset,
2446                                           HTMLImageElement* image, ExceptionCode& ec)
2447 {
2448     printWarningToConsole("Calling obsolete texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, HTMLImageElement image)");
2449     texSubImage2D(target, level, xoffset, yoffset, image, 0, 0, ec);
2450 }
2451
2452 void WebGLRenderingContext::texSubImage2D(unsigned target, unsigned level, unsigned xoffset, unsigned yoffset,
2453                                           HTMLImageElement* image, bool flipY, ExceptionCode& ec)
2454 {
2455     printWarningToConsole("Calling obsolete texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, HTMLImageElement image, GLboolean flipY)");
2456     texSubImage2D(target, level, xoffset, yoffset, image, flipY, 0, ec);
2457 }
2458
2459 void WebGLRenderingContext::texSubImage2D(unsigned target, unsigned level, unsigned xoffset, unsigned yoffset,
2460                                           HTMLImageElement* image, bool flipY, bool premultiplyAlpha, ExceptionCode& ec)
2461 {
2462     printWarningToConsole("Calling obsolete texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, HTMLImageElement image, GLboolean flipY, GLboolean premultiplyAlpha)");
2463     ec = 0;
2464     if (!image || !image->cachedImage()) {
2465         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
2466         return;
2467     }
2468     texSubImage2DImpl(target, level, xoffset, yoffset, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, image->cachedImage()->image(),
2469                       flipY, premultiplyAlpha, ec);
2470 }
2471
2472 void WebGLRenderingContext::texSubImage2D(unsigned target, unsigned level, unsigned xoffset, unsigned yoffset,
2473                                           HTMLCanvasElement* canvas, ExceptionCode& ec)
2474 {
2475     printWarningToConsole("Calling obsolete texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, HTMLCanvasElement canvas)");
2476     texSubImage2D(target, level, xoffset, yoffset, canvas, 0, 0, ec);
2477 }
2478
2479 void WebGLRenderingContext::texSubImage2D(unsigned target, unsigned level, unsigned xoffset, unsigned yoffset,
2480                                           HTMLCanvasElement* canvas, bool flipY, ExceptionCode& ec)
2481 {
2482     printWarningToConsole("Calling obsolete texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, HTMLCanvasElement canvas, GLboolean flipY)");
2483     texSubImage2D(target, level, xoffset, yoffset, canvas, flipY, 0, ec);
2484 }
2485
2486 void WebGLRenderingContext::texSubImage2D(unsigned target, unsigned level, unsigned xoffset, unsigned yoffset,
2487                                           HTMLCanvasElement* canvas, bool flipY, bool premultiplyAlpha, ExceptionCode& ec)
2488 {
2489     printWarningToConsole("Calling obsolete texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, HTMLCanvasElement canvas, GLboolean flipY, GLboolean premultiplyAlpha)");
2490     ec = 0;
2491     if (!canvas || !canvas->buffer()) {
2492         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
2493         return;
2494     }
2495     texSubImage2DImpl(target, level, xoffset, yoffset, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, canvas->buffer()->image(),
2496                       flipY, premultiplyAlpha, ec);
2497 }
2498
2499 void WebGLRenderingContext::texSubImage2D(unsigned target, unsigned level, unsigned xoffset, unsigned yoffset,
2500                                           HTMLVideoElement* video, ExceptionCode& ec)
2501 {
2502     texSubImage2D(target, level, xoffset, yoffset, video, 0, 0, ec);
2503 }
2504
2505 void WebGLRenderingContext::texSubImage2D(unsigned target, unsigned level, unsigned xoffset, unsigned yoffset,
2506                                           HTMLVideoElement* video, bool flipY, ExceptionCode& ec)
2507 {
2508     texSubImage2D(target, level, xoffset, yoffset, video, flipY, 0, ec);
2509 }
2510
2511 void WebGLRenderingContext::texSubImage2D(unsigned target, unsigned level, unsigned xoffset, unsigned yoffset,
2512                                           HTMLVideoElement* video, bool flipY, bool premultiplyAlpha, ExceptionCode& ec)
2513 {
2514     // FIXME: Need to implement this call
2515     UNUSED_PARAM(target);
2516     UNUSED_PARAM(level);
2517     UNUSED_PARAM(xoffset);
2518     UNUSED_PARAM(yoffset);
2519     UNUSED_PARAM(video);
2520     UNUSED_PARAM(flipY);
2521     UNUSED_PARAM(premultiplyAlpha);
2522     ec = 0;
2523     cleanupAfterGraphicsCall(false);
2524 }
2525
2526 void WebGLRenderingContext::uniform1f(const WebGLUniformLocation* location, float x, ExceptionCode& ec)
2527 {
2528     UNUSED_PARAM(ec);
2529     if (!location)
2530         return;
2531
2532     if (location->program() != m_currentProgram) {
2533         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
2534         return;
2535     }
2536
2537     m_context->uniform1f(location->location(), x);
2538     cleanupAfterGraphicsCall(false);
2539 }
2540
2541 void WebGLRenderingContext::uniform1fv(const WebGLUniformLocation* location, Float32Array* v, ExceptionCode& ec)
2542 {
2543     UNUSED_PARAM(ec);
2544     if (!validateUniformParameters(location, v, 1))
2545         return;
2546
2547     m_context->uniform1fv(location->location(), v->data(), v->length());
2548     cleanupAfterGraphicsCall(false);
2549 }
2550
2551 void WebGLRenderingContext::uniform1fv(const WebGLUniformLocation* location, float* v, int size, ExceptionCode& ec)
2552 {
2553     UNUSED_PARAM(ec);
2554     if (!validateUniformParameters(location, v, size, 1))
2555         return;
2556
2557     m_context->uniform1fv(location->location(), v, size);
2558     cleanupAfterGraphicsCall(false);
2559 }
2560
2561 void WebGLRenderingContext::uniform1i(const WebGLUniformLocation* location, int x, ExceptionCode& ec)
2562 {
2563     UNUSED_PARAM(ec);
2564     if (!location)
2565         return;
2566
2567     if (location->program() != m_currentProgram) {
2568         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
2569         return;
2570     }
2571
2572     m_context->uniform1i(location->location(), x);
2573     cleanupAfterGraphicsCall(false);
2574 }
2575
2576 void WebGLRenderingContext::uniform1iv(const WebGLUniformLocation* location, Int32Array* v, ExceptionCode& ec)
2577 {
2578     UNUSED_PARAM(ec);
2579     if (!validateUniformParameters(location, v, 1))
2580         return;
2581
2582     m_context->uniform1iv(location->location(), v->data(), v->length());
2583     cleanupAfterGraphicsCall(false);
2584 }
2585
2586 void WebGLRenderingContext::uniform1iv(const WebGLUniformLocation* location, int* v, int size, ExceptionCode& ec)
2587 {
2588     UNUSED_PARAM(ec);
2589     if (!validateUniformParameters(location, v, size, 1))
2590         return;
2591
2592     m_context->uniform1iv(location->location(), v, size);
2593     cleanupAfterGraphicsCall(false);
2594 }
2595
2596 void WebGLRenderingContext::uniform2f(const WebGLUniformLocation* location, float x, float y, ExceptionCode& ec)
2597 {
2598     UNUSED_PARAM(ec);
2599     if (!location)
2600         return;
2601
2602     if (location->program() != m_currentProgram) {
2603         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
2604         return;
2605     }
2606
2607     m_context->uniform2f(location->location(), x, y);
2608     cleanupAfterGraphicsCall(false);
2609 }
2610
2611 void WebGLRenderingContext::uniform2fv(const WebGLUniformLocation* location, Float32Array* v, ExceptionCode& ec)
2612 {
2613     UNUSED_PARAM(ec);
2614     if (!validateUniformParameters(location, v, 2))
2615         return;
2616
2617     m_context->uniform2fv(location->location(), v->data(), v->length() / 2);
2618     cleanupAfterGraphicsCall(false);
2619 }
2620
2621 void WebGLRenderingContext::uniform2fv(const WebGLUniformLocation* location, float* v, int size, ExceptionCode& ec)
2622 {
2623     UNUSED_PARAM(ec);
2624     if (!validateUniformParameters(location, v, size, 2))
2625         return;
2626
2627     m_context->uniform2fv(location->location(), v, size / 2);
2628     cleanupAfterGraphicsCall(false);
2629 }
2630
2631 void WebGLRenderingContext::uniform2i(const WebGLUniformLocation* location, int x, int y, ExceptionCode& ec)
2632 {
2633     UNUSED_PARAM(ec);
2634     if (!location)
2635         return;
2636
2637     if (location->program() != m_currentProgram) {
2638         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
2639         return;
2640     }
2641
2642     m_context->uniform2i(location->location(), x, y);
2643     cleanupAfterGraphicsCall(false);
2644 }
2645
2646 void WebGLRenderingContext::uniform2iv(const WebGLUniformLocation* location, Int32Array* v, ExceptionCode& ec)
2647 {
2648     UNUSED_PARAM(ec);
2649     if (!validateUniformParameters(location, v, 2))
2650         return;
2651
2652     m_context->uniform2iv(location->location(), v->data(), v->length() / 2);
2653     cleanupAfterGraphicsCall(false);
2654 }
2655
2656 void WebGLRenderingContext::uniform2iv(const WebGLUniformLocation* location, int* v, int size, ExceptionCode& ec)
2657 {
2658     UNUSED_PARAM(ec);
2659     if (!validateUniformParameters(location, v, size, 2))
2660         return;
2661
2662     m_context->uniform2iv(location->location(), v, size / 2);
2663     cleanupAfterGraphicsCall(false);
2664 }
2665
2666 void WebGLRenderingContext::uniform3f(const WebGLUniformLocation* location, float x, float y, float z, ExceptionCode& ec)
2667 {
2668     UNUSED_PARAM(ec);
2669     if (!location)
2670         return;
2671
2672     if (location->program() != m_currentProgram) {
2673         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
2674         return;
2675     }
2676
2677     m_context->uniform3f(location->location(), x, y, z);
2678     cleanupAfterGraphicsCall(false);
2679 }
2680
2681 void WebGLRenderingContext::uniform3fv(const WebGLUniformLocation* location, Float32Array* v, ExceptionCode& ec)
2682 {
2683     UNUSED_PARAM(ec);
2684     if (!validateUniformParameters(location, v, 3))
2685         return;
2686
2687     m_context->uniform3fv(location->location(), v->data(), v->length() / 3);
2688     cleanupAfterGraphicsCall(false);
2689 }
2690
2691 void WebGLRenderingContext::uniform3fv(const WebGLUniformLocation* location, float* v, int size, ExceptionCode& ec)
2692 {
2693     UNUSED_PARAM(ec);
2694     if (!validateUniformParameters(location, v, size, 3))
2695         return;
2696
2697     m_context->uniform3fv(location->location(), v, size / 3);
2698     cleanupAfterGraphicsCall(false);
2699 }
2700
2701 void WebGLRenderingContext::uniform3i(const WebGLUniformLocation* location, int x, int y, int z, ExceptionCode& ec)
2702 {
2703     UNUSED_PARAM(ec);
2704     if (!location)
2705         return;
2706
2707     if (location->program() != m_currentProgram) {
2708         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
2709         return;
2710     }
2711
2712     m_context->uniform3i(location->location(), x, y, z);
2713     cleanupAfterGraphicsCall(false);
2714 }
2715
2716 void WebGLRenderingContext::uniform3iv(const WebGLUniformLocation* location, Int32Array* v, ExceptionCode& ec)
2717 {
2718     UNUSED_PARAM(ec);
2719     if (!validateUniformParameters(location, v, 3))
2720         return;
2721
2722     m_context->uniform3iv(location->location(), v->data(), v->length() / 3);
2723     cleanupAfterGraphicsCall(false);
2724 }
2725
2726 void WebGLRenderingContext::uniform3iv(const WebGLUniformLocation* location, int* v, int size, ExceptionCode& ec)
2727 {
2728     UNUSED_PARAM(ec);
2729     if (!validateUniformParameters(location, v, size, 3))
2730         return;
2731
2732     m_context->uniform3iv(location->location(), v, size / 3);
2733     cleanupAfterGraphicsCall(false);
2734 }
2735
2736 void WebGLRenderingContext::uniform4f(const WebGLUniformLocation* location, float x, float y, float z, float w, ExceptionCode& ec)
2737 {
2738     UNUSED_PARAM(ec);
2739     if (!location)
2740         return;
2741
2742     if (location->program() != m_currentProgram) {
2743         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
2744         return;
2745     }
2746
2747     m_context->uniform4f(location->location(), x, y, z, w);
2748     cleanupAfterGraphicsCall(false);
2749 }
2750
2751 void WebGLRenderingContext::uniform4fv(const WebGLUniformLocation* location, Float32Array* v, ExceptionCode& ec)
2752 {
2753     UNUSED_PARAM(ec);
2754     if (!validateUniformParameters(location, v, 4))
2755         return;
2756
2757     m_context->uniform4fv(location->location(), v->data(), v->length() / 4);
2758     cleanupAfterGraphicsCall(false);
2759 }
2760
2761 void WebGLRenderingContext::uniform4fv(const WebGLUniformLocation* location, float* v, int size, ExceptionCode& ec)
2762 {
2763     UNUSED_PARAM(ec);
2764     if (!validateUniformParameters(location, v, size, 4))
2765         return;
2766
2767     m_context->uniform4fv(location->location(), v, size / 4);
2768     cleanupAfterGraphicsCall(false);
2769 }
2770
2771 void WebGLRenderingContext::uniform4i(const WebGLUniformLocation* location, int x, int y, int z, int w, ExceptionCode& ec)
2772 {
2773     UNUSED_PARAM(ec);
2774     if (!location)
2775         return;
2776
2777     if (location->program() != m_currentProgram) {
2778         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
2779         return;
2780     }
2781
2782     m_context->uniform4i(location->location(), x, y, z, w);
2783     cleanupAfterGraphicsCall(false);
2784 }
2785
2786 void WebGLRenderingContext::uniform4iv(const WebGLUniformLocation* location, Int32Array* v, ExceptionCode& ec)
2787 {
2788     UNUSED_PARAM(ec);
2789     if (!validateUniformParameters(location, v, 4))
2790         return;
2791
2792     m_context->uniform4iv(location->location(), v->data(), v->length() / 4);
2793     cleanupAfterGraphicsCall(false);
2794 }
2795
2796 void WebGLRenderingContext::uniform4iv(const WebGLUniformLocation* location, int* v, int size, ExceptionCode& ec)
2797 {
2798     UNUSED_PARAM(ec);
2799     if (!validateUniformParameters(location, v, size, 4))
2800         return;
2801
2802     m_context->uniform4iv(location->location(), v, size / 4);
2803     cleanupAfterGraphicsCall(false);
2804 }
2805
2806 void WebGLRenderingContext::uniformMatrix2fv(const WebGLUniformLocation* location, bool transpose, Float32Array* v, ExceptionCode& ec)
2807 {
2808     UNUSED_PARAM(ec);
2809     if (!validateUniformMatrixParameters(location, transpose, v, 4))
2810         return;
2811     m_context->uniformMatrix2fv(location->location(), transpose, v->data(), v->length() / 4);
2812     cleanupAfterGraphicsCall(false);
2813 }
2814
2815 void WebGLRenderingContext::uniformMatrix2fv(const WebGLUniformLocation* location, bool transpose, float* v, int size, ExceptionCode& ec)
2816 {
2817     UNUSED_PARAM(ec);
2818     if (!validateUniformMatrixParameters(location, transpose, v, size, 4))
2819         return;
2820     m_context->uniformMatrix2fv(location->location(), transpose, v, size / 4);
2821     cleanupAfterGraphicsCall(false);
2822 }
2823
2824 void WebGLRenderingContext::uniformMatrix3fv(const WebGLUniformLocation* location, bool transpose, Float32Array* v, ExceptionCode& ec)
2825 {
2826     UNUSED_PARAM(ec);
2827     if (!validateUniformMatrixParameters(location, transpose, v, 9))
2828         return;
2829     m_context->uniformMatrix3fv(location->location(), transpose, v->data(), v->length() / 9);
2830     cleanupAfterGraphicsCall(false);
2831 }
2832
2833 void WebGLRenderingContext::uniformMatrix3fv(const WebGLUniformLocation* location, bool transpose, float* v, int size, ExceptionCode& ec)
2834 {
2835     UNUSED_PARAM(ec);
2836     if (!validateUniformMatrixParameters(location, transpose, v, size, 9))
2837         return;
2838     m_context->uniformMatrix3fv(location->location(), transpose, v, size / 9);
2839     cleanupAfterGraphicsCall(false);
2840 }
2841
2842 void WebGLRenderingContext::uniformMatrix4fv(const WebGLUniformLocation* location, bool transpose, Float32Array* v, ExceptionCode& ec)
2843 {
2844     UNUSED_PARAM(ec);
2845     if (!validateUniformMatrixParameters(location, transpose, v, 16))
2846         return;
2847     m_context->uniformMatrix4fv(location->location(), transpose, v->data(), v->length() / 16);
2848     cleanupAfterGraphicsCall(false);
2849 }
2850
2851 void WebGLRenderingContext::uniformMatrix4fv(const WebGLUniformLocation* location, bool transpose, float* v, int size, ExceptionCode& ec)
2852 {
2853     UNUSED_PARAM(ec);
2854     if (!validateUniformMatrixParameters(location, transpose, v, size, 16))
2855         return;
2856     m_context->uniformMatrix4fv(location->location(), transpose, v, size / 16);
2857     cleanupAfterGraphicsCall(false);
2858 }
2859
2860 void WebGLRenderingContext::useProgram(WebGLProgram* program, ExceptionCode& ec)
2861 {
2862     UNUSED_PARAM(ec);
2863     if (program && program->context() != this) {
2864         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
2865         return;
2866     }
2867     m_currentProgram = program;
2868     m_context->useProgram(program);
2869     cleanupAfterGraphicsCall(false);
2870 }
2871
2872 void WebGLRenderingContext::validateProgram(WebGLProgram* program, ExceptionCode& ec)
2873 {
2874     UNUSED_PARAM(ec);
2875     if (!validateWebGLObject(program))
2876         return;
2877     m_context->validateProgram(program);
2878     cleanupAfterGraphicsCall(false);
2879 }
2880
2881 void WebGLRenderingContext::vertexAttrib1f(unsigned long index, float v0)
2882 {
2883     // In GL, we skip setting vertexAttrib0 values.
2884     if (index || isGLES2Compliant()) {
2885         m_context->vertexAttrib1f(index, v0);
2886         cleanupAfterGraphicsCall(false);
2887     }
2888     m_vertexAttribState[index].value[0] = v0;
2889     m_vertexAttribState[index].value[1] = 0.0f;
2890     m_vertexAttribState[index].value[2] = 0.0f;
2891     m_vertexAttribState[index].value[3] = 1.0f;
2892 }
2893
2894 void WebGLRenderingContext::vertexAttrib1fv(unsigned long index, Float32Array* v)
2895 {
2896     vertexAttribImpl(index, v, 1);
2897 }
2898
2899 void WebGLRenderingContext::vertexAttrib1fv(unsigned long index, float* v, int size)
2900 {
2901     vertexAttribImpl(index, v, size, 1);
2902 }
2903
2904 void WebGLRenderingContext::vertexAttrib2f(unsigned long index, float v0, float v1)
2905 {
2906     // In GL, we skip setting vertexAttrib0 values.
2907     if (index || isGLES2Compliant()) {
2908         m_context->vertexAttrib2f(index, v0, v1);
2909         cleanupAfterGraphicsCall(false);
2910     }
2911     m_vertexAttribState[index].value[0] = v0;
2912     m_vertexAttribState[index].value[1] = v1;
2913     m_vertexAttribState[index].value[2] = 0.0f;
2914     m_vertexAttribState[index].value[3] = 1.0f;
2915 }
2916
2917 void WebGLRenderingContext::vertexAttrib2fv(unsigned long index, Float32Array* v)
2918 {
2919     vertexAttribImpl(index, v, 2);
2920 }
2921
2922 void WebGLRenderingContext::vertexAttrib2fv(unsigned long index, float* v, int size)
2923 {
2924     vertexAttribImpl(index, v, size, 2);
2925 }
2926
2927 void WebGLRenderingContext::vertexAttrib3f(unsigned long index, float v0, float v1, float v2)
2928 {
2929     // In GL, we skip setting vertexAttrib0 values.
2930     if (index || isGLES2Compliant()) {
2931         m_context->vertexAttrib3f(index, v0, v1, v2);
2932         cleanupAfterGraphicsCall(false);
2933     }
2934     m_vertexAttribState[index].value[0] = v0;
2935     m_vertexAttribState[index].value[1] = v1;
2936     m_vertexAttribState[index].value[2] = v2;
2937     m_vertexAttribState[index].value[3] = 1.0f;
2938 }
2939
2940 void WebGLRenderingContext::vertexAttrib3fv(unsigned long index, Float32Array* v)
2941 {
2942     vertexAttribImpl(index, v, 3);
2943 }
2944
2945 void WebGLRenderingContext::vertexAttrib3fv(unsigned long index, float* v, int size)
2946 {
2947     vertexAttribImpl(index, v, size, 3);
2948 }
2949
2950 void WebGLRenderingContext::vertexAttrib4f(unsigned long index, float v0, float v1, float v2, float v3)
2951 {
2952     // In GL, we skip setting vertexAttrib0 values.
2953     if (index || isGLES2Compliant()) {
2954         m_context->vertexAttrib4f(index, v0, v1, v2, v3);
2955         cleanupAfterGraphicsCall(false);
2956     }
2957     m_vertexAttribState[index].value[0] = v0;
2958     m_vertexAttribState[index].value[1] = v1;
2959     m_vertexAttribState[index].value[2] = v2;
2960     m_vertexAttribState[index].value[3] = v3;
2961 }
2962
2963 void WebGLRenderingContext::vertexAttrib4fv(unsigned long index, Float32Array* v)
2964 {
2965     vertexAttribImpl(index, v, 4);
2966 }
2967
2968 void WebGLRenderingContext::vertexAttrib4fv(unsigned long index, float* v, int size)
2969 {
2970     vertexAttribImpl(index, v, size, 4);
2971 }
2972
2973 void WebGLRenderingContext::vertexAttribPointer(unsigned long index, long size, unsigned long type, bool normalized, long stride, long offset, ExceptionCode& ec)
2974 {
2975     if (index >= m_maxVertexAttribs) {
2976         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
2977         return;
2978     }
2979     if (size < 1 || size > 4 || stride < 0 || offset < 0) {
2980         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
2981         return;
2982     }
2983     if (!m_boundArrayBuffer) {
2984         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
2985         return;
2986     }
2987     // Determine the number of elements the bound buffer can hold, given the offset, size, type and stride
2988     long bytesPerElement = size * sizeInBytes(type, ec);
2989     if (bytesPerElement <= 0)
2990         return;
2991
2992     if (index >= m_vertexAttribState.size())
2993         m_vertexAttribState.resize(index + 1);
2994
2995     long validatedStride = bytesPerElement;
2996     if (stride != 0) {
2997         if ((long) stride < bytesPerElement) {
2998             m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
2999             return;
3000         }
3001         validatedStride = stride;
3002     }
3003     m_vertexAttribState[index].bufferBinding = m_boundArrayBuffer;
3004     m_vertexAttribState[index].bytesPerElement = bytesPerElement;
3005     m_vertexAttribState[index].size = size;
3006     m_vertexAttribState[index].type = type;
3007     m_vertexAttribState[index].normalized = normalized;
3008     m_vertexAttribState[index].stride = validatedStride;
3009     m_vertexAttribState[index].originalStride = stride;
3010     m_vertexAttribState[index].offset = offset;
3011     m_context->vertexAttribPointer(index, size, type, normalized, stride, offset);
3012     cleanupAfterGraphicsCall(false);
3013 }
3014
3015 void WebGLRenderingContext::viewport(long x, long y, unsigned long width, unsigned long height)
3016 {
3017     if (isnan(x))
3018         x = 0;
3019     if (isnan(y))
3020         y = 0;
3021     if (isnan(width))
3022         width = 100;
3023     if (isnan(height))
3024         height = 100;
3025     m_context->viewport(x, y, width, height);
3026     cleanupAfterGraphicsCall(false);
3027 }
3028
3029 void WebGLRenderingContext::removeObject(CanvasObject* object)
3030 {
3031     m_canvasObjects.remove(object);
3032 }
3033
3034 void WebGLRenderingContext::addObject(CanvasObject* object)
3035 {
3036     removeObject(object);
3037     m_canvasObjects.add(object);
3038 }
3039
3040 void WebGLRenderingContext::detachAndRemoveAllObjects()
3041 {
3042     HashSet<RefPtr<CanvasObject> >::iterator pend = m_canvasObjects.end();
3043     for (HashSet<RefPtr<CanvasObject> >::iterator it = m_canvasObjects.begin(); it != pend; ++it)
3044         (*it)->detachContext();
3045         
3046     m_canvasObjects.clear();
3047 }
3048
3049 WebGLTexture* WebGLRenderingContext::findTexture(Platform3DObject obj)
3050 {
3051     if (!obj)
3052         return 0;
3053     HashSet<RefPtr<CanvasObject> >::iterator pend = m_canvasObjects.end();
3054     for (HashSet<RefPtr<CanvasObject> >::iterator it = m_canvasObjects.begin(); it != pend; ++it) {
3055         if ((*it)->isTexture() && (*it)->object() == obj)
3056             return reinterpret_cast<WebGLTexture*>((*it).get());
3057     }
3058     return 0;
3059 }
3060
3061 WebGLRenderbuffer* WebGLRenderingContext::findRenderbuffer(Platform3DObject obj)
3062 {
3063     if (!obj)
3064         return 0;
3065     HashSet<RefPtr<CanvasObject> >::iterator pend = m_canvasObjects.end();
3066     for (HashSet<RefPtr<CanvasObject> >::iterator it = m_canvasObjects.begin(); it != pend; ++it) {
3067         if ((*it)->isRenderbuffer() && (*it)->object() == obj)
3068             return reinterpret_cast<WebGLRenderbuffer*>((*it).get());
3069     }
3070     return 0;
3071 }
3072
3073 WebGLBuffer* WebGLRenderingContext::findBuffer(Platform3DObject obj)
3074 {
3075     if (!obj)
3076         return 0;
3077     HashSet<RefPtr<CanvasObject> >::iterator pend = m_canvasObjects.end();
3078     for (HashSet<RefPtr<CanvasObject> >::iterator it = m_canvasObjects.begin(); it != pend; ++it) {
3079         if ((*it)->isBuffer() && (*it)->object() == obj)
3080             return reinterpret_cast<WebGLBuffer*>((*it).get());
3081     }
3082     return 0;
3083 }
3084
3085 WebGLShader* WebGLRenderingContext::findShader(Platform3DObject obj)
3086 {
3087     if (!obj)
3088         return 0;
3089     HashSet<RefPtr<CanvasObject> >::iterator pend = m_canvasObjects.end();
3090     for (HashSet<RefPtr<CanvasObject> >::iterator it = m_canvasObjects.begin(); it != pend; ++it) {
3091         if ((*it)->isShader() && (*it)->object() == obj)
3092             return reinterpret_cast<WebGLShader*>((*it).get());
3093     }
3094     return 0;
3095 }
3096
3097 WebGLGetInfo WebGLRenderingContext::getBooleanParameter(unsigned long pname)
3098 {
3099     unsigned char value;
3100     m_context->getBooleanv(pname, &value);
3101     return WebGLGetInfo(static_cast<bool>(value));
3102 }
3103
3104 WebGLGetInfo WebGLRenderingContext::getBooleanArrayParameter(unsigned long pname)
3105 {
3106     if (pname != GraphicsContext3D::COLOR_WRITEMASK) {
3107         notImplemented();
3108         return WebGLGetInfo(0, 0);
3109     }
3110     unsigned char value[4] = {0};
3111     m_context->getBooleanv(pname, value);
3112     bool boolValue[4];
3113     for (int ii = 0; ii < 4; ++ii)
3114         boolValue[ii] = static_cast<bool>(value[ii]);
3115     return WebGLGetInfo(boolValue, 4);
3116 }
3117
3118 WebGLGetInfo WebGLRenderingContext::getFloatParameter(unsigned long pname)
3119 {
3120     float value;
3121     m_context->getFloatv(pname, &value);
3122     return WebGLGetInfo(static_cast<float>(value));
3123 }
3124
3125 WebGLGetInfo WebGLRenderingContext::getIntParameter(unsigned long pname)
3126 {
3127     return getLongParameter(pname);
3128 }
3129
3130 WebGLGetInfo WebGLRenderingContext::getLongParameter(unsigned long pname)
3131 {
3132     int value;
3133     m_context->getIntegerv(pname, &value);
3134     return WebGLGetInfo(static_cast<long>(value));
3135 }
3136
3137 WebGLGetInfo WebGLRenderingContext::getUnsignedLongParameter(unsigned long pname)
3138 {
3139     int value;
3140     m_context->getIntegerv(pname, &value);
3141     return WebGLGetInfo(static_cast<unsigned long>(value));
3142 }
3143
3144 WebGLGetInfo WebGLRenderingContext::getWebGLFloatArrayParameter(unsigned long pname)
3145 {
3146     float value[4] = {0};
3147     m_context->getFloatv(pname, value);
3148     unsigned length = 0;
3149     switch (pname) {
3150     case GraphicsContext3D::ALIASED_POINT_SIZE_RANGE:
3151     case GraphicsContext3D::ALIASED_LINE_WIDTH_RANGE:
3152     case GraphicsContext3D::DEPTH_RANGE:
3153         length = 2;
3154         break;
3155     case GraphicsContext3D::BLEND_COLOR:
3156     case GraphicsContext3D::COLOR_CLEAR_VALUE:
3157         length = 4;
3158         break;
3159     default:
3160         notImplemented();
3161     }
3162     return WebGLGetInfo(Float32Array::create(value, length));
3163 }
3164
3165 WebGLGetInfo WebGLRenderingContext::getWebGLIntArrayParameter(unsigned long pname)
3166 {
3167     int value[4] = {0};
3168     m_context->getIntegerv(pname, value);
3169     unsigned length = 0;
3170     switch (pname) {
3171     case GraphicsContext3D::MAX_VIEWPORT_DIMS:
3172         length = 2;
3173         break;
3174     case GraphicsContext3D::SCISSOR_BOX:
3175     case GraphicsContext3D::VIEWPORT:
3176         length = 4;
3177         break;
3178     default:
3179         notImplemented();
3180     }
3181     return WebGLGetInfo(Int32Array::create(value, length));
3182 }
3183
3184 bool WebGLRenderingContext::isGLES2Compliant()
3185 {
3186     return m_context->isGLES2Compliant();
3187 }
3188
3189 void WebGLRenderingContext::handleNPOTTextures(bool prepareToDraw)
3190 {
3191     bool resetActiveUnit = false;
3192     for (unsigned ii = 0; ii < m_textureUnits.size(); ++ii) {
3193         if (m_textureUnits[ii].m_texture2DBinding && m_textureUnits[ii].m_texture2DBinding->needToUseBlackTexture()
3194             || m_textureUnits[ii].m_textureCubeMapBinding && m_textureUnits[ii].m_textureCubeMapBinding->needToUseBlackTexture()) {
3195             if (ii != m_activeTextureUnit) {
3196                 m_context->activeTexture(ii);
3197                 resetActiveUnit = true;
3198             } else if (resetActiveUnit) {
3199                 m_context->activeTexture(ii);
3200                 resetActiveUnit = false;
3201             }
3202             WebGLTexture* tex2D;
3203             WebGLTexture* texCubeMap;
3204             if (prepareToDraw) {
3205                 tex2D = m_blackTexture2D.get();
3206                 texCubeMap = m_blackTextureCubeMap.get();
3207             } else {
3208                 tex2D = m_textureUnits[ii].m_texture2DBinding.get();
3209                 texCubeMap = m_textureUnits[ii].m_textureCubeMapBinding.get();
3210             }
3211             if (m_textureUnits[ii].m_texture2DBinding && m_textureUnits[ii].m_texture2DBinding->needToUseBlackTexture())
3212                 m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, tex2D);
3213             if (m_textureUnits[ii].m_textureCubeMapBinding && m_textureUnits[ii].m_textureCubeMapBinding->needToUseBlackTexture())
3214                 m_context->bindTexture(GraphicsContext3D::TEXTURE_CUBE_MAP, texCubeMap);
3215         }
3216     }
3217     if (resetActiveUnit)
3218         m_context->activeTexture(m_activeTextureUnit);
3219 }
3220
3221 void WebGLRenderingContext::createFallbackBlackTextures1x1()
3222 {
3223     unsigned char black[] = {0, 0, 0, 255};
3224     m_blackTexture2D = createTexture();
3225     m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_blackTexture2D.get());
3226     m_context->texImage2D(GraphicsContext3D::TEXTURE_2D, 0, GraphicsContext3D::RGBA, 1, 1,
3227                           0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, black);
3228     m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, 0);
3229     m_blackTextureCubeMap = createTexture();
3230     m_context->bindTexture(GraphicsContext3D::TEXTURE_CUBE_MAP, m_blackTextureCubeMap.get());
3231     m_context->texImage2D(GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_X, 0, GraphicsContext3D::RGBA, 1, 1,
3232                           0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, black);
3233     m_context->texImage2D(GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GraphicsContext3D::RGBA, 1, 1,
3234                           0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, black);
3235     m_context->texImage2D(GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GraphicsContext3D::RGBA, 1, 1,
3236                           0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, black);
3237     m_context->texImage2D(GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GraphicsContext3D::RGBA, 1, 1,
3238                           0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, black);
3239     m_context->texImage2D(GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GraphicsContext3D::RGBA, 1, 1,
3240                           0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, black);
3241     m_context->texImage2D(GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GraphicsContext3D::RGBA, 1, 1,
3242                           0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, black);
3243     m_context->bindTexture(GraphicsContext3D::TEXTURE_CUBE_MAP, 0);
3244 }
3245
3246 bool WebGLRenderingContext::isTexInternalFormatColorBufferCombinationValid(unsigned long texInternalFormat,
3247                                                                            unsigned long colorBufferFormat)
3248 {
3249     switch (colorBufferFormat) {
3250     case GraphicsContext3D::ALPHA:
3251         if (texInternalFormat == GraphicsContext3D::ALPHA)
3252             return true;
3253         break;
3254     case GraphicsContext3D::RGB:
3255         if (texInternalFormat == GraphicsContext3D::LUMINANCE
3256             || texInternalFormat == GraphicsContext3D::RGB)
3257             return true;
3258         break;
3259     case GraphicsContext3D::RGBA:
3260         return true;
3261     }
3262     return false;
3263 }
3264
3265 WebGLTexture* WebGLRenderingContext::getTextureBinding(unsigned long target)
3266 {
3267     RefPtr<WebGLTexture> tex = 0;
3268     switch (target) {
3269     case GraphicsContext3D::TEXTURE_2D:
3270         tex = m_textureUnits[m_activeTextureUnit].m_texture2DBinding;
3271         break;
3272     case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_X:
3273     case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_X:
3274     case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Y:
3275     case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Y:
3276     case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Z:
3277     case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Z:
3278         tex = m_textureUnits[m_activeTextureUnit].m_textureCubeMapBinding;
3279         break;
3280     }
3281     if (tex && tex->object())
3282         return tex.get();
3283     return 0;
3284 }
3285
3286 bool WebGLRenderingContext::validateTexFuncFormatAndType(unsigned long format, unsigned long type)
3287 {
3288     switch (format) {
3289     case GraphicsContext3D::ALPHA:
3290     case GraphicsContext3D::LUMINANCE:
3291     case GraphicsContext3D::LUMINANCE_ALPHA:
3292     case GraphicsContext3D::RGB:
3293     case GraphicsContext3D::RGBA:
3294         break;
3295     default:
3296         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
3297         return false;
3298     }
3299
3300     switch (type) {
3301     case GraphicsContext3D::UNSIGNED_BYTE:
3302     case GraphicsContext3D::UNSIGNED_SHORT_5_6_5:
3303     case GraphicsContext3D::UNSIGNED_SHORT_4_4_4_4:
3304     case GraphicsContext3D::UNSIGNED_SHORT_5_5_5_1:
3305         break;
3306     default:
3307         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
3308         return false;
3309     }
3310
3311     // Verify that the combination of format and type is supported.
3312     switch (format) {
3313     case GraphicsContext3D::ALPHA:
3314     case GraphicsContext3D::LUMINANCE:
3315     case GraphicsContext3D::LUMINANCE_ALPHA:
3316         if (type != GraphicsContext3D::UNSIGNED_BYTE) {
3317             m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
3318             return false;
3319         }
3320         break;
3321     case GraphicsContext3D::RGB:
3322         if (type != GraphicsContext3D::UNSIGNED_BYTE
3323             && type != GraphicsContext3D::UNSIGNED_SHORT_5_6_5) {
3324             m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
3325             return false;
3326         }
3327         break;
3328     case GraphicsContext3D::RGBA:
3329         if (type != GraphicsContext3D::UNSIGNED_BYTE
3330             && type != GraphicsContext3D::UNSIGNED_SHORT_4_4_4_4
3331             && type != GraphicsContext3D::UNSIGNED_SHORT_5_5_5_1) {
3332             m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
3333             return false;
3334         }
3335         break;
3336     default:
3337         ASSERT_NOT_REACHED();
3338     }
3339
3340     return true;
3341 }
3342
3343 bool WebGLRenderingContext::validateTexFuncParameters(unsigned long target, long level,
3344                                                       unsigned long internalformat,
3345                                                       long width, long height, long border,
3346                                                       unsigned long format, unsigned long type)
3347 {
3348     // We absolutely have to validate the format and type combination.
3349     // The texImage2D entry points taking HTMLImage, etc. will produce
3350     // temporary data based on this combination, so it must be legal.
3351     if (!validateTexFuncFormatAndType(format, type))
3352         return false;
3353
3354     if (isGLES2Compliant())
3355         return true;
3356
3357     if (width < 0 || height < 0 || level < 0) {
3358         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
3359         return false;
3360     }
3361
3362     switch (target) {
3363     case GraphicsContext3D::TEXTURE_2D:
3364         if (width > m_maxTextureSize || height > m_maxTextureSize) {
3365             m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
3366             return false;
3367         }
3368         break;
3369     case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_X:
3370     case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_X:
3371     case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Y:
3372     case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Y:
3373     case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Z:
3374     case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Z:
3375         if (width != height || width > m_maxCubeMapTextureSize) {
3376             m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
3377             return false;
3378         }
3379         break;
3380     default:
3381         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
3382         return false;
3383     }
3384
3385     if (format != internalformat) {
3386         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
3387         return false;
3388     }
3389
3390     if (border) {
3391         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
3392         return false;
3393     }
3394
3395     return true;
3396 }
3397
3398 bool WebGLRenderingContext::validateTexFuncData(long width, long height,
3399                                                 unsigned long format, unsigned long type,
3400                                                 ArrayBufferView* pixels)
3401 {
3402     if (!pixels)
3403         return true;
3404
3405     if (!validateTexFuncFormatAndType(format, type))
3406         return false;
3407
3408     switch (type) {
3409     case GraphicsContext3D::UNSIGNED_BYTE:
3410         if (!pixels->isUnsignedByteArray()) {
3411             m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
3412             return false;
3413         }
3414         break;
3415     case GraphicsContext3D::UNSIGNED_SHORT_5_6_5:
3416     case GraphicsContext3D::UNSIGNED_SHORT_4_4_4_4:
3417     case GraphicsContext3D::UNSIGNED_SHORT_5_5_5_1:
3418         if (!pixels->isUnsignedShortArray()) {
3419             m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
3420             return false;
3421         }
3422         break;
3423     default:
3424         ASSERT_NOT_REACHED();
3425     }
3426
3427     unsigned long componentsPerPixel, bytesPerComponent;
3428     if (!m_context->computeFormatAndTypeParameters(format, type, &componentsPerPixel, &bytesPerComponent)) {
3429         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
3430         return false;
3431     }
3432
3433     if (!width || !height)
3434         return true;
3435     unsigned int validRowBytes = width * componentsPerPixel * bytesPerComponent;
3436     unsigned int totalRowBytes = validRowBytes;
3437     unsigned int remainder = validRowBytes % m_unpackAlignment;
3438     if (remainder)
3439         totalRowBytes += (m_unpackAlignment - remainder);
3440     unsigned int totalBytesRequired = (height - 1) * totalRowBytes + validRowBytes;
3441     if (pixels->byteLength() < totalBytesRequired) {
3442         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
3443         return false;
3444     }
3445     return true;
3446 }
3447
3448 bool WebGLRenderingContext::validateDrawMode(unsigned long mode)
3449 {
3450     switch (mode) {
3451     case GraphicsContext3D::POINTS:
3452     case GraphicsContext3D::LINE_STRIP:
3453     case GraphicsContext3D::LINE_LOOP:
3454     case GraphicsContext3D::LINES:
3455     case GraphicsContext3D::TRIANGLE_STRIP:
3456     case GraphicsContext3D::TRIANGLE_FAN:
3457     case GraphicsContext3D::TRIANGLES:
3458         return true;
3459     default:
3460         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
3461         return false;
3462     }
3463 }
3464
3465 void WebGLRenderingContext::printWarningToConsole(const String& message)
3466 {
3467     canvas()->document()->frame()->domWindow()->console()->addMessage(HTMLMessageSource, LogMessageType, WarningMessageLevel,
3468                                                                       message, 0, canvas()->document()->url().string());
3469 }
3470
3471 bool WebGLRenderingContext::validateFramebufferFuncParameters(unsigned long target, unsigned long attachment)
3472 {
3473     if (target != GraphicsContext3D::FRAMEBUFFER) {
3474         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
3475         return false;
3476     }
3477     switch (attachment) {
3478     case GraphicsContext3D::COLOR_ATTACHMENT0:
3479     case GraphicsContext3D::DEPTH_ATTACHMENT:
3480     case GraphicsContext3D::STENCIL_ATTACHMENT:
3481     case GraphicsContext3D::DEPTH_STENCIL_ATTACHMENT:
3482         break;
3483     default:
3484         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
3485         return false;
3486     }
3487     return true;
3488 }
3489
3490 bool WebGLRenderingContext::validateBlendEquation(unsigned long mode)
3491 {
3492     switch (mode) {
3493     case GraphicsContext3D::FUNC_ADD:
3494     case GraphicsContext3D::FUNC_SUBTRACT:
3495     case GraphicsContext3D::FUNC_REVERSE_SUBTRACT:
3496         return true;
3497     default:
3498         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
3499         return false;
3500     }
3501 }
3502
3503 bool WebGLRenderingContext::validateCapability(unsigned long cap)
3504 {
3505     switch (cap) {
3506     case GraphicsContext3D::BLEND:
3507     case GraphicsContext3D::CULL_FACE:
3508     case GraphicsContext3D::DEPTH_TEST:
3509     case GraphicsContext3D::DITHER:
3510     case GraphicsContext3D::POLYGON_OFFSET_FILL:
3511     case GraphicsContext3D::SAMPLE_ALPHA_TO_COVERAGE:
3512     case GraphicsContext3D::SAMPLE_COVERAGE:
3513     case GraphicsContext3D::SCISSOR_TEST:
3514     case GraphicsContext3D::STENCIL_TEST:
3515         return true;
3516     default:
3517         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
3518         return false;
3519     }
3520 }
3521
3522 bool WebGLRenderingContext::validateUniformParameters(const WebGLUniformLocation* location, Float32Array* v, int requiredMinSize)
3523 {
3524     if (!v) {
3525         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
3526         return false;
3527     }
3528     return validateUniformMatrixParameters(location, false, v->data(), v->length(), requiredMinSize);
3529 }
3530
3531 bool WebGLRenderingContext::validateUniformParameters(const WebGLUniformLocation* location, Int32Array* v, int requiredMinSize)
3532 {
3533     if (!v) {
3534         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
3535         return false;
3536     }
3537     return validateUniformMatrixParameters(location, false, v->data(), v->length(), requiredMinSize);
3538 }
3539
3540 bool WebGLRenderingContext::validateUniformParameters(const WebGLUniformLocation* location, void* v, int size, int requiredMinSize)
3541 {
3542     return validateUniformMatrixParameters(location, false, v, size, requiredMinSize);
3543 }
3544
3545 bool WebGLRenderingContext::validateUniformMatrixParameters(const WebGLUniformLocation* location, bool transpose, Float32Array* v, int requiredMinSize)
3546 {
3547     if (!v) {
3548         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
3549         return false;
3550     }
3551     return validateUniformMatrixParameters(location, transpose, v->data(), v->length(), requiredMinSize);
3552 }
3553
3554 bool WebGLRenderingContext::validateUniformMatrixParameters(const WebGLUniformLocation* location, bool transpose, void* v, int size, int requiredMinSize)
3555 {
3556     if (!location)
3557         return false;
3558     if (location->program() != m_currentProgram) {
3559         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
3560         return false;
3561     }
3562     if (!v) {
3563         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
3564         return false;
3565     }
3566     if (transpose) {
3567         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
3568         return false;
3569     }
3570     if (size < requiredMinSize) {
3571         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
3572         return false;
3573     }
3574     return true;
3575 }
3576
3577 void WebGLRenderingContext::vertexAttribImpl(unsigned long index, Float32Array* v, int expectedSize)
3578 {
3579     if (!v) {
3580         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
3581         return;
3582     }
3583     vertexAttribImpl(index, v->data(), v->length(), expectedSize);
3584 }
3585
3586 void WebGLRenderingContext::vertexAttribImpl(unsigned long index, float* v, int size, int expectedSize)
3587 {
3588     if (!v) {
3589         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
3590         return;
3591     }
3592     if (size < expectedSize) {
3593         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
3594         return;
3595     }
3596     // In GL, we skip setting vertexAttrib0 values.
3597     if (index || isGLES2Compliant()) {
3598         switch (expectedSize) {
3599         case 1:
3600             m_context->vertexAttrib1fv(index, v);
3601             break;
3602         case 2:
3603             m_context->vertexAttrib2fv(index, v);
3604             break;
3605         case 3:
3606             m_context->vertexAttrib3fv(index, v);
3607             break;
3608         case 4:
3609             m_context->vertexAttrib4fv(index, v);
3610             break;
3611         }
3612         cleanupAfterGraphicsCall(false);
3613     }
3614     m_vertexAttribState[index].initValue();
3615     for (int ii = 0; ii < expectedSize; ++ii)
3616         m_vertexAttribState[index].value[ii] = v[ii];
3617 }
3618
3619 void WebGLRenderingContext::initVertexAttrib0()
3620 {
3621     m_vertexAttribState.resize(1);
3622     m_vertexAttrib0Buffer = createBuffer();
3623     m_context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, m_vertexAttrib0Buffer.get());
3624     m_context->bufferData(GraphicsContext3D::ARRAY_BUFFER, 0, GraphicsContext3D::DYNAMIC_DRAW);
3625     m_context->vertexAttribPointer(0, 4, GraphicsContext3D::FLOAT, false, 0, 0);
3626     m_vertexAttribState[0].bufferBinding = m_vertexAttrib0Buffer;
3627     m_context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, 0);
3628     m_context->enableVertexAttribArray(0);
3629     m_vertexAttrib0BufferSize = 0;
3630     m_vertexAttrib0BufferValue[0] = 0.0f;
3631     m_vertexAttrib0BufferValue[1] = 0.0f;
3632     m_vertexAttrib0BufferValue[2] = 0.0f;
3633     m_vertexAttrib0BufferValue[3] = 1.0f;
3634 }
3635
3636 bool WebGLRenderingContext::simulateVertexAttrib0(long numVertex)
3637 {
3638     const VertexAttribState& state = m_vertexAttribState[0];
3639     if (state.enabled || !m_currentProgram || !m_currentProgram->object()
3640         || !m_currentProgram->isUsingVertexAttrib0())
3641         return false;
3642     m_context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, m_vertexAttrib0Buffer.get());
3643     long bufferDataSize = (numVertex + 1) * 4 * sizeof(float);
3644     if (bufferDataSize > m_vertexAttrib0BufferSize
3645         || state.value[0] != m_vertexAttrib0BufferValue[0]
3646         || state.value[1] != m_vertexAttrib0BufferValue[1]
3647         || state.value[2] != m_vertexAttrib0BufferValue[2]
3648         || state.value[3] != m_vertexAttrib0BufferValue[3]) {
3649         RefPtr<Float32Array> bufferData = Float32Array::create((numVertex + 1) * 4);
3650         for (long ii = 0; ii < numVertex + 1; ++ii) {
3651             bufferData->set(ii * 4, state.value[0]);
3652             bufferData->set(ii * 4 + 1, state.value[1]);
3653             bufferData->set(ii * 4 + 2, state.value[2]);
3654             bufferData->set(ii * 4 + 3, state.value[3]);
3655         }
3656         m_context->bufferData(GraphicsContext3D::ARRAY_BUFFER, bufferData.get(), GraphicsContext3D::DYNAMIC_DRAW);
3657         m_vertexAttrib0BufferSize = bufferDataSize;
3658         m_vertexAttrib0BufferValue[0] = state.value[0];
3659         m_vertexAttrib0BufferValue[1] = state.value[1];
3660         m_vertexAttrib0BufferValue[2] = state.value[2];
3661         m_vertexAttrib0BufferValue[3] = state.value[3];
3662     }
3663     m_context->vertexAttribPointer(0, 4, GraphicsContext3D::FLOAT, false, 0, 0);
3664     return true;
3665 }
3666
3667 void WebGLRenderingContext::restoreStatesAfterVertexAttrib0Simulation()
3668 {
3669     const VertexAttribState& state = m_vertexAttribState[0];
3670     if (state.bufferBinding != m_vertexAttrib0Buffer) {
3671         m_context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, state.bufferBinding.get());
3672         m_context->vertexAttribPointer(0, state.size, state.type, state.normalized, state.originalStride, state.offset);
3673     }
3674     m_context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, m_boundArrayBuffer.get());
3675 }
3676
3677 } // namespace WebCore
3678
3679 #endif // ENABLE(3D_CANVAS)