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