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