• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "WebKitLoseContext.h"
36 #include "Console.h"
37 #include "DOMWindow.h"
38 #include "Extensions3D.h"
39 #include "FrameView.h"
40 #include "HTMLCanvasElement.h"
41 #include "HTMLImageElement.h"
42 #include "HTMLVideoElement.h"
43 #include "ImageBuffer.h"
44 #include "ImageData.h"
45 #include "IntSize.h"
46 #include "NotImplemented.h"
47 #include "OESStandardDerivatives.h"
48 #include "OESTextureFloat.h"
49 #include "OESVertexArrayObject.h"
50 #include "RenderBox.h"
51 #include "RenderLayer.h"
52 #include "Settings.h"
53 #include "Uint16Array.h"
54 #include "WebGLActiveInfo.h"
55 #include "WebGLBuffer.h"
56 #include "WebGLContextAttributes.h"
57 #include "WebGLContextEvent.h"
58 #include "WebGLFramebuffer.h"
59 #include "WebGLProgram.h"
60 #include "WebGLRenderbuffer.h"
61 #include "WebGLShader.h"
62 #include "WebGLTexture.h"
63 #include "WebGLUniformLocation.h"
64 
65 #include <wtf/ByteArray.h>
66 #include <wtf/OwnArrayPtr.h>
67 #include <wtf/PassOwnArrayPtr.h>
68 #include <wtf/text/StringBuilder.h>
69 
70 #if PLATFORM(QT)
71 #undef emit
72 #endif
73 
74 namespace WebCore {
75 
76 const double secondsBetweenRestoreAttempts = 1.0;
77 
78 namespace {
79 
objectOrZero(WebGLObject * object)80     Platform3DObject objectOrZero(WebGLObject* object)
81     {
82         return object ? object->object() : 0;
83     }
84 
clip1D(GC3Dint start,GC3Dsizei range,GC3Dsizei sourceRange,GC3Dint * clippedStart,GC3Dsizei * clippedRange)85     void clip1D(GC3Dint start, GC3Dsizei range, GC3Dsizei sourceRange, GC3Dint* clippedStart, GC3Dsizei* clippedRange)
86     {
87         ASSERT(clippedStart && clippedRange);
88         if (start < 0) {
89             range += start;
90             start = 0;
91         }
92         GC3Dint end = start + range;
93         if (end > sourceRange)
94             range -= end - sourceRange;
95         *clippedStart = start;
96         *clippedRange = range;
97     }
98 
99     // Returns false if no clipping is necessary, i.e., x, y, width, height stay the same.
clip2D(GC3Dint x,GC3Dint y,GC3Dsizei width,GC3Dsizei height,GC3Dsizei sourceWidth,GC3Dsizei sourceHeight,GC3Dint * clippedX,GC3Dint * clippedY,GC3Dsizei * clippedWidth,GC3Dsizei * clippedHeight)100     bool clip2D(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height,
101                 GC3Dsizei sourceWidth, GC3Dsizei sourceHeight,
102                 GC3Dint* clippedX, GC3Dint* clippedY, GC3Dsizei* clippedWidth, GC3Dsizei*clippedHeight)
103     {
104         ASSERT(clippedX && clippedY && clippedWidth && clippedHeight);
105         clip1D(x, width, sourceWidth, clippedX, clippedWidth);
106         clip1D(y, height, sourceHeight, clippedY, clippedHeight);
107         return (*clippedX != x || *clippedY != y || *clippedWidth != width || *clippedHeight != height);
108     }
109 
110     // Return true if a character belongs to the ASCII subset as defined in
111     // GLSL ES 1.0 spec section 3.1.
validateCharacter(unsigned char c)112     bool validateCharacter(unsigned char c)
113     {
114         // Printing characters are valid except " $ ` @ \ ' DEL.
115         if (c >= 32 && c <= 126
116             && c != '"' && c != '$' && c != '`' && c != '@' && c != '\\' && c != '\'')
117             return true;
118         // Horizontal tab, line feed, vertical tab, form feed, carriage return
119         // are also valid.
120         if (c >= 9 && c <= 13)
121             return true;
122         return false;
123     }
124 
125     // Strips comments from shader text. This allows non-ASCII characters
126     // to be used in comments without potentially breaking OpenGL
127     // implementations not expecting characters outside the GLSL ES set.
128     class StripComments {
129     public:
StripComments(const String & str)130         StripComments(const String& str)
131             : m_parseState(BeginningOfLine)
132             , m_sourceString(str)
133             , m_length(str.length())
134             , m_position(0)
135         {
136             parse();
137         }
138 
result()139         String result()
140         {
141             return m_builder.toString();
142         }
143 
144     private:
hasMoreCharacters()145         bool hasMoreCharacters()
146         {
147             return (m_position < m_length);
148         }
149 
parse()150         void parse()
151         {
152             while (hasMoreCharacters()) {
153                 process(current());
154                 // process() might advance the position.
155                 if (hasMoreCharacters())
156                     advance();
157             }
158         }
159 
160         void process(UChar);
161 
peek(UChar & character)162         bool peek(UChar& character)
163         {
164             if (m_position + 1 >= m_length)
165                 return false;
166             character = m_sourceString[m_position + 1];
167             return true;
168         }
169 
current()170         UChar current()
171         {
172             ASSERT(m_position < m_length);
173             return m_sourceString[m_position];
174         }
175 
advance()176         void advance()
177         {
178             ++m_position;
179         }
180 
isNewline(UChar character)181         bool isNewline(UChar character)
182         {
183             // Don't attempt to canonicalize newline related characters.
184             return (character == '\n' || character == '\r');
185         }
186 
emit(UChar character)187         void emit(UChar character)
188         {
189             m_builder.append(character);
190         }
191 
192         enum ParseState {
193             // Have not seen an ASCII non-whitespace character yet on
194             // this line. Possible that we might see a preprocessor
195             // directive.
196             BeginningOfLine,
197 
198             // Have seen at least one ASCII non-whitespace character
199             // on this line.
200             MiddleOfLine,
201 
202             // Handling a preprocessor directive. Passes through all
203             // characters up to the end of the line. Disables comment
204             // processing.
205             InPreprocessorDirective,
206 
207             // Handling a single-line comment. The comment text is
208             // replaced with a single space.
209             InSingleLineComment,
210 
211             // Handling a multi-line comment. Newlines are passed
212             // through to preserve line numbers.
213             InMultiLineComment
214         };
215 
216         ParseState m_parseState;
217         String m_sourceString;
218         unsigned m_length;
219         unsigned m_position;
220         StringBuilder m_builder;
221     };
222 
process(UChar c)223     void StripComments::process(UChar c)
224     {
225         if (isNewline(c)) {
226             // No matter what state we are in, pass through newlines
227             // so we preserve line numbers.
228             emit(c);
229 
230             if (m_parseState != InMultiLineComment)
231                 m_parseState = BeginningOfLine;
232 
233             return;
234         }
235 
236         UChar temp = 0;
237         switch (m_parseState) {
238         case BeginningOfLine:
239             if (WTF::isASCIISpace(c)) {
240                 emit(c);
241                 break;
242             }
243 
244             if (c == '#') {
245                 m_parseState = InPreprocessorDirective;
246                 emit(c);
247                 break;
248             }
249 
250             // Transition to normal state and re-handle character.
251             m_parseState = MiddleOfLine;
252             process(c);
253             break;
254 
255         case MiddleOfLine:
256             if (c == '/' && peek(temp)) {
257                 if (temp == '/') {
258                     m_parseState = InSingleLineComment;
259                     emit(' ');
260                     advance();
261                     break;
262                 }
263 
264                 if (temp == '*') {
265                     m_parseState = InMultiLineComment;
266                     // Emit the comment start in case the user has
267                     // an unclosed comment and we want to later
268                     // signal an error.
269                     emit('/');
270                     emit('*');
271                     advance();
272                     break;
273                 }
274             }
275 
276             emit(c);
277             break;
278 
279         case InPreprocessorDirective:
280             // No matter what the character is, just pass it
281             // through. Do not parse comments in this state. This
282             // might not be the right thing to do long term, but it
283             // should handle the #error preprocessor directive.
284             emit(c);
285             break;
286 
287         case InSingleLineComment:
288             // The newline code at the top of this function takes care
289             // of resetting our state when we get out of the
290             // single-line comment. Swallow all other characters.
291             break;
292 
293         case InMultiLineComment:
294             if (c == '*' && peek(temp) && temp == '/') {
295                 emit('*');
296                 emit('/');
297                 m_parseState = MiddleOfLine;
298                 advance();
299                 break;
300             }
301 
302             // Swallow all other characters. Unclear whether we may
303             // want or need to just emit a space per character to try
304             // to preserve column numbers for debugging purposes.
305             break;
306         }
307     }
308 } // namespace anonymous
309 
310 class WebGLStateRestorer {
311 public:
WebGLStateRestorer(WebGLRenderingContext * context,bool changed)312     WebGLStateRestorer(WebGLRenderingContext* context,
313                        bool changed)
314         : m_context(context)
315         , m_changed(changed)
316     {
317     }
318 
~WebGLStateRestorer()319     ~WebGLStateRestorer()
320     {
321         m_context->cleanupAfterGraphicsCall(m_changed);
322     }
323 
324 private:
325     WebGLRenderingContext* m_context;
326     bool m_changed;
327 };
328 
fired()329 void WebGLRenderingContext::WebGLRenderingContextRestoreTimer::fired()
330 {
331     // Timer is started when m_contextLost is false.  It will first call
332     // onLostContext, which will set m_contextLost to true.  Then it will keep
333     // calling restoreContext and reschedule itself until m_contextLost is back
334     // to false.
335     if (!m_context->m_contextLost) {
336         m_context->onLostContext();
337         startOneShot(secondsBetweenRestoreAttempts);
338     } else {
339         // The rendering context is not restored if there is no handler for
340         // the context restored event.
341         if (!m_context->canvas()->hasEventListeners(eventNames().webglcontextrestoredEvent))
342             return;
343 
344         m_context->restoreContext();
345         if (m_context->m_contextLost)
346             startOneShot(secondsBetweenRestoreAttempts);
347     }
348 }
349 
350 class WebGLRenderingContextLostCallback : public GraphicsContext3D::ContextLostCallback {
351 public:
WebGLRenderingContextLostCallback(WebGLRenderingContext * cb)352     WebGLRenderingContextLostCallback(WebGLRenderingContext* cb) : m_contextLostCallback(cb) {}
onContextLost()353     virtual void onContextLost() { m_contextLostCallback->forceLostContext(); }
~WebGLRenderingContextLostCallback()354     virtual ~WebGLRenderingContextLostCallback() {}
355 private:
356     WebGLRenderingContext* m_contextLostCallback;
357 };
358 
create(HTMLCanvasElement * canvas,WebGLContextAttributes * attrs)359 PassOwnPtr<WebGLRenderingContext> WebGLRenderingContext::create(HTMLCanvasElement* canvas, WebGLContextAttributes* attrs)
360 {
361     HostWindow* hostWindow = canvas->document()->view()->root()->hostWindow();
362     GraphicsContext3D::Attributes attributes = attrs ? attrs->attributes() : GraphicsContext3D::Attributes();
363 
364     if (attributes.antialias) {
365         Page* p = canvas->document()->page();
366         if (p && !p->settings()->openGLMultisamplingEnabled())
367             attributes.antialias = false;
368     }
369 
370     RefPtr<GraphicsContext3D> context(GraphicsContext3D::create(attributes, hostWindow));
371 
372     if (!context) {
373         canvas->dispatchEvent(WebGLContextEvent::create(eventNames().webglcontextcreationerrorEvent, false, true, "Could not create a WebGL context."));
374         return 0;
375     }
376 
377     return new WebGLRenderingContext(canvas, context, attributes);
378 }
379 
WebGLRenderingContext(HTMLCanvasElement * passedCanvas,PassRefPtr<GraphicsContext3D> context,GraphicsContext3D::Attributes attributes)380 WebGLRenderingContext::WebGLRenderingContext(HTMLCanvasElement* passedCanvas, PassRefPtr<GraphicsContext3D> context,
381                                              GraphicsContext3D::Attributes attributes)
382     : CanvasRenderingContext(passedCanvas)
383     , m_context(context)
384     , m_restoreTimer(this)
385     , m_videoCache(4)
386     , m_contextLost(false)
387     , m_attributes(attributes)
388 {
389     ASSERT(m_context);
390     setupFlags();
391     initializeNewContext();
392 }
393 
initializeNewContext()394 void WebGLRenderingContext::initializeNewContext()
395 {
396     ASSERT(!m_contextLost);
397     m_needsUpdate = true;
398     m_markedCanvasDirty = false;
399     m_activeTextureUnit = 0;
400     m_packAlignment = 4;
401     m_unpackAlignment = 4;
402     m_unpackFlipY = false;
403     m_unpackPremultiplyAlpha = false;
404     m_unpackColorspaceConversion = GraphicsContext3D::BROWSER_DEFAULT_WEBGL;
405     m_boundArrayBuffer = 0;
406     m_currentProgram = 0;
407     m_framebufferBinding = 0;
408     m_renderbufferBinding = 0;
409     m_stencilMask = 0xFFFFFFFF;
410     m_stencilMaskBack = 0xFFFFFFFF;
411     m_stencilFuncRef = 0;
412     m_stencilFuncRefBack = 0;
413     m_stencilFuncMask = 0xFFFFFFFF;
414     m_stencilFuncMaskBack = 0xFFFFFFFF;
415     m_layerCleared = false;
416 
417     m_clearColor[0] = m_clearColor[1] = m_clearColor[2] = m_clearColor[3] = 0;
418     m_scissorEnabled = false;
419     m_clearDepth = 1;
420     m_clearStencil = 0;
421     m_colorMask[0] = m_colorMask[1] = m_colorMask[2] = m_colorMask[3] = true;
422 
423     GC3Dint numCombinedTextureImageUnits = 0;
424     m_context->getIntegerv(GraphicsContext3D::MAX_COMBINED_TEXTURE_IMAGE_UNITS, &numCombinedTextureImageUnits);
425     m_textureUnits.clear();
426     m_textureUnits.resize(numCombinedTextureImageUnits);
427 
428     GC3Dint numVertexAttribs = 0;
429     m_context->getIntegerv(GraphicsContext3D::MAX_VERTEX_ATTRIBS, &numVertexAttribs);
430     m_maxVertexAttribs = numVertexAttribs;
431 
432     m_maxTextureSize = 0;
433     m_context->getIntegerv(GraphicsContext3D::MAX_TEXTURE_SIZE, &m_maxTextureSize);
434     m_maxTextureLevel = WebGLTexture::computeLevelCount(m_maxTextureSize, m_maxTextureSize);
435     m_maxCubeMapTextureSize = 0;
436     m_context->getIntegerv(GraphicsContext3D::MAX_CUBE_MAP_TEXTURE_SIZE, &m_maxCubeMapTextureSize);
437     m_maxCubeMapTextureLevel = WebGLTexture::computeLevelCount(m_maxCubeMapTextureSize, m_maxCubeMapTextureSize);
438 
439     m_defaultVertexArrayObject = WebGLVertexArrayObjectOES::create(this, WebGLVertexArrayObjectOES::VaoTypeDefault);
440     addObject(m_defaultVertexArrayObject.get());
441     m_boundVertexArrayObject = m_defaultVertexArrayObject;
442 
443     m_vertexAttribValue.resize(m_maxVertexAttribs);
444 
445     if (!isGLES2NPOTStrict())
446         createFallbackBlackTextures1x1();
447     if (!isGLES2Compliant())
448         initVertexAttrib0();
449 
450     m_context->reshape(canvas()->width(), canvas()->height());
451     m_context->viewport(0, 0, canvas()->width(), canvas()->height());
452 
453     m_context->setContextLostCallback(adoptPtr(new WebGLRenderingContextLostCallback(this)));
454 }
455 
setupFlags()456 void WebGLRenderingContext::setupFlags()
457 {
458     ASSERT(m_context);
459 
460     m_isGLES2Compliant = m_context->isGLES2Compliant();
461     m_isErrorGeneratedOnOutOfBoundsAccesses = m_context->getExtensions()->isEnabled("GL_CHROMIUM_strict_attribs");
462     m_isResourceSafe = m_context->getExtensions()->isEnabled("GL_CHROMIUM_resource_safe");
463     if (m_isGLES2Compliant) {
464         m_isGLES2NPOTStrict = !m_context->getExtensions()->isEnabled("GL_OES_texture_npot");
465         m_isDepthStencilSupported = m_context->getExtensions()->isEnabled("GL_OES_packed_depth_stencil");
466     } else {
467         m_isGLES2NPOTStrict = !m_context->getExtensions()->isEnabled("GL_ARB_texture_non_power_of_two");
468         m_isDepthStencilSupported = m_context->getExtensions()->isEnabled("GL_EXT_packed_depth_stencil");
469     }
470 }
471 
~WebGLRenderingContext()472 WebGLRenderingContext::~WebGLRenderingContext()
473 {
474     detachAndRemoveAllObjects();
475     m_context->setContextLostCallback(0);
476     if (m_webkitLoseContext)
477         m_webkitLoseContext->contextDestroyed();
478 }
479 
markContextChanged()480 void WebGLRenderingContext::markContextChanged()
481 {
482     if (m_framebufferBinding)
483         return;
484     m_context->markContextChanged();
485     m_layerCleared = false;
486 #if USE(ACCELERATED_COMPOSITING)
487     RenderBox* renderBox = canvas()->renderBox();
488     if (renderBox && renderBox->hasLayer() && renderBox->layer()->hasAcceleratedCompositing())
489         renderBox->layer()->contentChanged(RenderLayer::CanvasChanged);
490     else {
491 #endif
492         if (!m_markedCanvasDirty)
493             canvas()->didDraw(FloatRect(0, 0, canvas()->width(), canvas()->height()));
494 #if USE(ACCELERATED_COMPOSITING)
495     }
496 #endif
497     m_markedCanvasDirty = true;
498 }
499 
clearIfComposited(GC3Dbitfield mask)500 bool WebGLRenderingContext::clearIfComposited(GC3Dbitfield mask)
501 {
502     if (isContextLost())
503         return false;
504 
505     if (!m_context->layerComposited() || m_layerCleared
506         || m_attributes.preserveDrawingBuffer || m_framebufferBinding)
507         return false;
508 
509     RefPtr<WebGLContextAttributes> contextAttributes = getContextAttributes();
510 
511     // Determine if it's possible to combine the clear the user asked for and this clear.
512     bool combinedClear = mask && !m_scissorEnabled;
513 
514     m_context->disable(GraphicsContext3D::SCISSOR_TEST);
515     if (combinedClear && (mask & GraphicsContext3D::COLOR_BUFFER_BIT))
516         m_context->clearColor(m_colorMask[0] ? m_clearColor[0] : 0,
517                               m_colorMask[1] ? m_clearColor[1] : 0,
518                               m_colorMask[2] ? m_clearColor[2] : 0,
519                               m_colorMask[3] ? m_clearColor[3] : 0);
520     else
521         m_context->clearColor(0, 0, 0, 0);
522     m_context->colorMask(true, true, true, true);
523     if (contextAttributes->depth() && (!combinedClear || !(mask & GraphicsContext3D::DEPTH_BUFFER_BIT)))
524         m_context->clearDepth(1.0f);
525     if (contextAttributes->stencil() && (!combinedClear || !(mask & GraphicsContext3D::STENCIL_BUFFER_BIT)))
526         m_context->clearStencil(0);
527     GC3Dbitfield clearMask = GraphicsContext3D::COLOR_BUFFER_BIT;
528     if (contextAttributes->depth())
529         clearMask |= GraphicsContext3D::DEPTH_BUFFER_BIT;
530     if (contextAttributes->stencil())
531         clearMask |= GraphicsContext3D::STENCIL_BUFFER_BIT;
532     m_context->clear(clearMask);
533 
534     // Restore the state that the context set.
535     if (m_scissorEnabled)
536         m_context->enable(GraphicsContext3D::SCISSOR_TEST);
537     m_context->clearColor(m_clearColor[0], m_clearColor[1],
538                           m_clearColor[2], m_clearColor[3]);
539     m_context->colorMask(m_colorMask[0], m_colorMask[1],
540                          m_colorMask[2], m_colorMask[3]);
541     m_context->clearDepth(m_clearDepth);
542     m_context->clearStencil(m_clearStencil);
543     m_layerCleared = true;
544 
545     return combinedClear;
546 }
547 
markLayerComposited()548 void WebGLRenderingContext::markLayerComposited()
549 {
550     m_context->markLayerComposited();
551 }
552 
paintRenderingResultsToCanvas()553 void WebGLRenderingContext::paintRenderingResultsToCanvas()
554 {
555     // Until the canvas is written to by the application, the clear that
556     // happened after it was composited should be ignored by the compositor.
557     if (m_context->layerComposited() && !m_attributes.preserveDrawingBuffer)
558         canvas()->makePresentationCopy();
559     else
560         canvas()->clearPresentationCopy();
561     clearIfComposited();
562     if (!m_markedCanvasDirty && !m_layerCleared)
563         return;
564     canvas()->clearCopiedImage();
565     m_markedCanvasDirty = false;
566     m_context->paintRenderingResultsToCanvas(this);
567 }
568 
paintRenderingResultsToImageData()569 PassRefPtr<ImageData> WebGLRenderingContext::paintRenderingResultsToImageData()
570 {
571     clearIfComposited();
572     return m_context->paintRenderingResultsToImageData();
573 }
574 
paintsIntoCanvasBuffer() const575 bool WebGLRenderingContext::paintsIntoCanvasBuffer() const
576 {
577     return m_context->paintsIntoCanvasBuffer();
578 }
579 
reshape(int width,int height)580 void WebGLRenderingContext::reshape(int width, int height)
581 {
582     if (m_needsUpdate) {
583 #if USE(ACCELERATED_COMPOSITING)
584         RenderBox* renderBox = canvas()->renderBox();
585         if (renderBox && renderBox->hasLayer())
586             renderBox->layer()->contentChanged(RenderLayer::CanvasChanged);
587 #endif
588         m_needsUpdate = false;
589     }
590 
591     // We don't have to mark the canvas as dirty, since the newly created image buffer will also start off
592     // clear (and this matches what reshape will do).
593     m_context->reshape(width, height);
594 }
595 
sizeInBytes(GC3Denum type)596 unsigned int WebGLRenderingContext::sizeInBytes(GC3Denum type)
597 {
598     switch (type) {
599     case GraphicsContext3D::BYTE:
600         return sizeof(GC3Dbyte);
601     case GraphicsContext3D::UNSIGNED_BYTE:
602         return sizeof(GC3Dubyte);
603     case GraphicsContext3D::SHORT:
604         return sizeof(GC3Dshort);
605     case GraphicsContext3D::UNSIGNED_SHORT:
606         return sizeof(GC3Dushort);
607     case GraphicsContext3D::INT:
608         return sizeof(GC3Dint);
609     case GraphicsContext3D::UNSIGNED_INT:
610         return sizeof(GC3Duint);
611     case GraphicsContext3D::FLOAT:
612         return sizeof(GC3Dfloat);
613     }
614     ASSERT_NOT_REACHED();
615     return 0;
616 }
617 
activeTexture(GC3Denum texture,ExceptionCode & ec)618 void WebGLRenderingContext::activeTexture(GC3Denum texture, ExceptionCode& ec)
619 {
620     UNUSED_PARAM(ec);
621     if (isContextLost())
622         return;
623     if (texture - GraphicsContext3D::TEXTURE0 >= m_textureUnits.size()) {
624         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
625         return;
626     }
627     m_activeTextureUnit = texture - GraphicsContext3D::TEXTURE0;
628     m_context->activeTexture(texture);
629     cleanupAfterGraphicsCall(false);
630 }
631 
attachShader(WebGLProgram * program,WebGLShader * shader,ExceptionCode & ec)632 void WebGLRenderingContext::attachShader(WebGLProgram* program, WebGLShader* shader, ExceptionCode& ec)
633 {
634     UNUSED_PARAM(ec);
635     if (isContextLost() || !validateWebGLObject(program) || !validateWebGLObject(shader))
636         return;
637     if (!program->attachShader(shader)) {
638         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
639         return;
640     }
641     m_context->attachShader(objectOrZero(program), objectOrZero(shader));
642     shader->onAttached();
643     cleanupAfterGraphicsCall(false);
644 }
645 
bindAttribLocation(WebGLProgram * program,GC3Duint index,const String & name,ExceptionCode & ec)646 void WebGLRenderingContext::bindAttribLocation(WebGLProgram* program, GC3Duint index, const String& name, ExceptionCode& ec)
647 {
648     UNUSED_PARAM(ec);
649     if (isContextLost() || !validateWebGLObject(program))
650         return;
651     if (!validateString(name))
652         return;
653     m_context->bindAttribLocation(objectOrZero(program), index, name);
654     cleanupAfterGraphicsCall(false);
655 }
656 
checkObjectToBeBound(WebGLObject * object,bool & deleted)657 bool WebGLRenderingContext::checkObjectToBeBound(WebGLObject* object, bool& deleted)
658 {
659     deleted = false;
660     if (isContextLost())
661         return false;
662     if (object) {
663         if (object->context() != this) {
664             m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
665             return false;
666         }
667         deleted = !object->object();
668     }
669     return true;
670 }
671 
bindBuffer(GC3Denum target,WebGLBuffer * buffer,ExceptionCode & ec)672 void WebGLRenderingContext::bindBuffer(GC3Denum target, WebGLBuffer* buffer, ExceptionCode& ec)
673 {
674     UNUSED_PARAM(ec);
675     bool deleted;
676     if (!checkObjectToBeBound(buffer, deleted))
677         return;
678     if (deleted)
679         buffer = 0;
680     if (buffer && buffer->getTarget() && buffer->getTarget() != target) {
681         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
682         return;
683     }
684     if (target == GraphicsContext3D::ARRAY_BUFFER)
685         m_boundArrayBuffer = buffer;
686     else if (target == GraphicsContext3D::ELEMENT_ARRAY_BUFFER)
687         m_boundVertexArrayObject->setElementArrayBuffer(buffer);
688     else {
689         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
690         return;
691     }
692 
693     m_context->bindBuffer(target, objectOrZero(buffer));
694     if (buffer)
695         buffer->setTarget(target);
696     cleanupAfterGraphicsCall(false);
697 }
698 
bindFramebuffer(GC3Denum target,WebGLFramebuffer * buffer,ExceptionCode & ec)699 void WebGLRenderingContext::bindFramebuffer(GC3Denum target, WebGLFramebuffer* buffer, ExceptionCode& ec)
700 {
701     UNUSED_PARAM(ec);
702     bool deleted;
703     if (!checkObjectToBeBound(buffer, deleted))
704         return;
705     if (deleted)
706         buffer = 0;
707     if (target != GraphicsContext3D::FRAMEBUFFER) {
708         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
709         return;
710     }
711     m_framebufferBinding = buffer;
712     m_context->bindFramebuffer(target, objectOrZero(buffer));
713     if (buffer)
714         buffer->setHasEverBeenBound();
715     cleanupAfterGraphicsCall(false);
716 }
717 
bindRenderbuffer(GC3Denum target,WebGLRenderbuffer * renderBuffer,ExceptionCode & ec)718 void WebGLRenderingContext::bindRenderbuffer(GC3Denum target, WebGLRenderbuffer* renderBuffer, ExceptionCode& ec)
719 {
720     UNUSED_PARAM(ec);
721     bool deleted;
722     if (!checkObjectToBeBound(renderBuffer, deleted))
723         return;
724     if (deleted)
725         renderBuffer = 0;
726     if (target != GraphicsContext3D::RENDERBUFFER) {
727         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
728         return;
729     }
730     m_renderbufferBinding = renderBuffer;
731     m_context->bindRenderbuffer(target, objectOrZero(renderBuffer));
732     if (renderBuffer)
733         renderBuffer->setHasEverBeenBound();
734     cleanupAfterGraphicsCall(false);
735 }
736 
bindTexture(GC3Denum target,WebGLTexture * texture,ExceptionCode & ec)737 void WebGLRenderingContext::bindTexture(GC3Denum target, WebGLTexture* texture, ExceptionCode& ec)
738 {
739     UNUSED_PARAM(ec);
740     bool deleted;
741     if (!checkObjectToBeBound(texture, deleted))
742         return;
743     if (deleted)
744         texture = 0;
745     if (texture && texture->getTarget() && texture->getTarget() != target) {
746         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
747         return;
748     }
749     GC3Dint maxLevel = 0;
750     if (target == GraphicsContext3D::TEXTURE_2D) {
751         m_textureUnits[m_activeTextureUnit].m_texture2DBinding = texture;
752         maxLevel = m_maxTextureLevel;
753     } else if (target == GraphicsContext3D::TEXTURE_CUBE_MAP) {
754         m_textureUnits[m_activeTextureUnit].m_textureCubeMapBinding = texture;
755         maxLevel = m_maxCubeMapTextureLevel;
756     } else {
757         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
758         return;
759     }
760     m_context->bindTexture(target, objectOrZero(texture));
761     if (texture)
762         texture->setTarget(target, maxLevel);
763 
764     // Note: previously we used to automatically set the TEXTURE_WRAP_R
765     // repeat mode to CLAMP_TO_EDGE for cube map textures, because OpenGL
766     // ES 2.0 doesn't expose this flag (a bug in the specification) and
767     // otherwise the application has no control over the seams in this
768     // dimension. However, it appears that supporting this properly on all
769     // platforms is fairly involved (will require a HashMap from texture ID
770     // in all ports), and we have not had any complaints, so the logic has
771     // been removed.
772 
773     cleanupAfterGraphicsCall(false);
774 }
775 
blendColor(GC3Dfloat red,GC3Dfloat green,GC3Dfloat blue,GC3Dfloat alpha)776 void WebGLRenderingContext::blendColor(GC3Dfloat red, GC3Dfloat green, GC3Dfloat blue, GC3Dfloat alpha)
777 {
778     if (isContextLost())
779         return;
780     m_context->blendColor(red, green, blue, alpha);
781     cleanupAfterGraphicsCall(false);
782 }
783 
blendEquation(GC3Denum mode)784 void WebGLRenderingContext::blendEquation(GC3Denum mode)
785 {
786     if (isContextLost() || !validateBlendEquation(mode))
787         return;
788     m_context->blendEquation(mode);
789     cleanupAfterGraphicsCall(false);
790 }
791 
blendEquationSeparate(GC3Denum modeRGB,GC3Denum modeAlpha)792 void WebGLRenderingContext::blendEquationSeparate(GC3Denum modeRGB, GC3Denum modeAlpha)
793 {
794     if (isContextLost() || !validateBlendEquation(modeRGB) || !validateBlendEquation(modeAlpha))
795         return;
796     m_context->blendEquationSeparate(modeRGB, modeAlpha);
797     cleanupAfterGraphicsCall(false);
798 }
799 
800 
blendFunc(GC3Denum sfactor,GC3Denum dfactor)801 void WebGLRenderingContext::blendFunc(GC3Denum sfactor, GC3Denum dfactor)
802 {
803     if (isContextLost() || !validateBlendFuncFactors(sfactor, dfactor))
804         return;
805     m_context->blendFunc(sfactor, dfactor);
806     cleanupAfterGraphicsCall(false);
807 }
808 
blendFuncSeparate(GC3Denum srcRGB,GC3Denum dstRGB,GC3Denum srcAlpha,GC3Denum dstAlpha)809 void WebGLRenderingContext::blendFuncSeparate(GC3Denum srcRGB, GC3Denum dstRGB, GC3Denum srcAlpha, GC3Denum dstAlpha)
810 {
811     if (isContextLost() || !validateBlendFuncFactors(srcRGB, dstRGB))
812         return;
813     m_context->blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha);
814     cleanupAfterGraphicsCall(false);
815 }
816 
bufferData(GC3Denum target,GC3Dsizeiptr size,GC3Denum usage,ExceptionCode & ec)817 void WebGLRenderingContext::bufferData(GC3Denum target, GC3Dsizeiptr size, GC3Denum usage, ExceptionCode& ec)
818 {
819     UNUSED_PARAM(ec);
820     if (isContextLost())
821         return;
822     WebGLBuffer* buffer = validateBufferDataParameters(target, usage);
823     if (!buffer)
824         return;
825     if (size < 0) {
826         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
827         return;
828     }
829     if (!isErrorGeneratedOnOutOfBoundsAccesses()) {
830         if (!buffer->associateBufferData(size)) {
831             m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
832             return;
833         }
834     }
835 
836     m_context->bufferData(target, size, usage);
837     cleanupAfterGraphicsCall(false);
838 }
839 
bufferData(GC3Denum target,ArrayBuffer * data,GC3Denum usage,ExceptionCode & ec)840 void WebGLRenderingContext::bufferData(GC3Denum target, ArrayBuffer* data, GC3Denum usage, ExceptionCode& ec)
841 {
842     UNUSED_PARAM(ec);
843     if (isContextLost())
844         return;
845     WebGLBuffer* buffer = validateBufferDataParameters(target, usage);
846     if (!buffer)
847         return;
848     if (!data) {
849         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
850         return;
851     }
852     if (!isErrorGeneratedOnOutOfBoundsAccesses()) {
853         if (!buffer->associateBufferData(data)) {
854             m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
855             return;
856         }
857     }
858 
859     m_context->bufferData(target, data->byteLength(), data->data(), usage);
860     cleanupAfterGraphicsCall(false);
861 }
862 
bufferData(GC3Denum target,ArrayBufferView * data,GC3Denum usage,ExceptionCode & ec)863 void WebGLRenderingContext::bufferData(GC3Denum target, ArrayBufferView* data, GC3Denum usage, ExceptionCode& ec)
864 {
865     UNUSED_PARAM(ec);
866     if (isContextLost())
867         return;
868     WebGLBuffer* buffer = validateBufferDataParameters(target, usage);
869     if (!buffer)
870         return;
871     if (!data) {
872         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
873         return;
874     }
875     if (!isErrorGeneratedOnOutOfBoundsAccesses()) {
876         if (!buffer->associateBufferData(data)) {
877             m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
878             return;
879         }
880     }
881 
882     m_context->bufferData(target, data->byteLength(), data->baseAddress(), usage);
883     cleanupAfterGraphicsCall(false);
884 }
885 
bufferSubData(GC3Denum target,GC3Dintptr offset,ArrayBuffer * data,ExceptionCode & ec)886 void WebGLRenderingContext::bufferSubData(GC3Denum target, GC3Dintptr offset, ArrayBuffer* data, ExceptionCode& ec)
887 {
888     UNUSED_PARAM(ec);
889     if (isContextLost())
890         return;
891     WebGLBuffer* buffer = validateBufferDataParameters(target, GraphicsContext3D::STATIC_DRAW);
892     if (!buffer)
893         return;
894     if (offset < 0) {
895         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
896         return;
897     }
898     if (!data)
899         return;
900     if (!isErrorGeneratedOnOutOfBoundsAccesses()) {
901         if (!buffer->associateBufferSubData(offset, data)) {
902             m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
903             return;
904         }
905     }
906 
907     m_context->bufferSubData(target, offset, data->byteLength(), data->data());
908     cleanupAfterGraphicsCall(false);
909 }
910 
bufferSubData(GC3Denum target,GC3Dintptr offset,ArrayBufferView * data,ExceptionCode & ec)911 void WebGLRenderingContext::bufferSubData(GC3Denum target, GC3Dintptr offset, ArrayBufferView* data, ExceptionCode& ec)
912 {
913     UNUSED_PARAM(ec);
914     if (isContextLost())
915         return;
916     WebGLBuffer* buffer = validateBufferDataParameters(target, GraphicsContext3D::STATIC_DRAW);
917     if (!buffer)
918         return;
919     if (offset < 0) {
920         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
921         return;
922     }
923     if (!data)
924         return;
925     if (!isErrorGeneratedOnOutOfBoundsAccesses()) {
926         if (!buffer->associateBufferSubData(offset, data)) {
927             m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
928             return;
929         }
930     }
931 
932     m_context->bufferSubData(target, offset, data->byteLength(), data->baseAddress());
933     cleanupAfterGraphicsCall(false);
934 }
935 
checkFramebufferStatus(GC3Denum target)936 GC3Denum WebGLRenderingContext::checkFramebufferStatus(GC3Denum target)
937 {
938     if (isContextLost())
939         return GraphicsContext3D::FRAMEBUFFER_UNSUPPORTED;
940     if (target != GraphicsContext3D::FRAMEBUFFER) {
941         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
942         return 0;
943     }
944     if (!m_framebufferBinding || !m_framebufferBinding->object())
945         return GraphicsContext3D::FRAMEBUFFER_COMPLETE;
946     if (m_framebufferBinding->isIncomplete(true))
947         return GraphicsContext3D::FRAMEBUFFER_UNSUPPORTED;
948     unsigned long result = m_context->checkFramebufferStatus(target);
949     cleanupAfterGraphicsCall(false);
950     return result;
951 }
952 
clear(GC3Dbitfield mask)953 void WebGLRenderingContext::clear(GC3Dbitfield mask)
954 {
955     if (isContextLost())
956         return;
957     if (mask & ~(GraphicsContext3D::COLOR_BUFFER_BIT | GraphicsContext3D::DEPTH_BUFFER_BIT | GraphicsContext3D::STENCIL_BUFFER_BIT)) {
958         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
959         return;
960     }
961     if (m_framebufferBinding && !m_framebufferBinding->onAccess(!isResourceSafe())) {
962         m_context->synthesizeGLError(GraphicsContext3D::INVALID_FRAMEBUFFER_OPERATION);
963         return;
964     }
965     if (!clearIfComposited(mask))
966         m_context->clear(mask);
967     cleanupAfterGraphicsCall(true);
968 }
969 
clearColor(GC3Dfloat r,GC3Dfloat g,GC3Dfloat b,GC3Dfloat a)970 void WebGLRenderingContext::clearColor(GC3Dfloat r, GC3Dfloat g, GC3Dfloat b, GC3Dfloat a)
971 {
972     if (isContextLost())
973         return;
974     if (isnan(r))
975         r = 0;
976     if (isnan(g))
977         g = 0;
978     if (isnan(b))
979         b = 0;
980     if (isnan(a))
981         a = 1;
982     m_clearColor[0] = r;
983     m_clearColor[1] = g;
984     m_clearColor[2] = b;
985     m_clearColor[3] = a;
986     m_context->clearColor(r, g, b, a);
987     cleanupAfterGraphicsCall(false);
988 }
989 
clearDepth(GC3Dfloat depth)990 void WebGLRenderingContext::clearDepth(GC3Dfloat depth)
991 {
992     if (isContextLost())
993         return;
994     m_clearDepth = depth;
995     m_context->clearDepth(depth);
996     cleanupAfterGraphicsCall(false);
997 }
998 
clearStencil(GC3Dint s)999 void WebGLRenderingContext::clearStencil(GC3Dint s)
1000 {
1001     if (isContextLost())
1002         return;
1003     m_clearStencil = s;
1004     m_context->clearStencil(s);
1005     cleanupAfterGraphicsCall(false);
1006 }
1007 
colorMask(GC3Dboolean red,GC3Dboolean green,GC3Dboolean blue,GC3Dboolean alpha)1008 void WebGLRenderingContext::colorMask(GC3Dboolean red, GC3Dboolean green, GC3Dboolean blue, GC3Dboolean alpha)
1009 {
1010     if (isContextLost())
1011         return;
1012     m_colorMask[0] = red;
1013     m_colorMask[1] = green;
1014     m_colorMask[2] = blue;
1015     m_colorMask[3] = alpha;
1016     m_context->colorMask(red, green, blue, alpha);
1017     cleanupAfterGraphicsCall(false);
1018 }
1019 
compileShader(WebGLShader * shader,ExceptionCode & ec)1020 void WebGLRenderingContext::compileShader(WebGLShader* shader, ExceptionCode& ec)
1021 {
1022     UNUSED_PARAM(ec);
1023     if (isContextLost() || !validateWebGLObject(shader))
1024         return;
1025     m_context->compileShader(objectOrZero(shader));
1026     cleanupAfterGraphicsCall(false);
1027 }
1028 
copyTexImage2D(GC3Denum target,GC3Dint level,GC3Denum internalformat,GC3Dint x,GC3Dint y,GC3Dsizei width,GC3Dsizei height,GC3Dint border)1029 void WebGLRenderingContext::copyTexImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height, GC3Dint border)
1030 {
1031     if (isContextLost())
1032         return;
1033     if (!validateTexFuncParameters(target, level, internalformat, width, height, border, internalformat, GraphicsContext3D::UNSIGNED_BYTE))
1034         return;
1035     WebGLTexture* tex = validateTextureBinding(target, true);
1036     if (!tex)
1037         return;
1038     if (!isTexInternalFormatColorBufferCombinationValid(internalformat, getBoundFramebufferColorFormat())) {
1039         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
1040         return;
1041     }
1042     if (!isGLES2NPOTStrict() && level && WebGLTexture::isNPOT(width, height)) {
1043         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
1044         return;
1045     }
1046     if (m_framebufferBinding && !m_framebufferBinding->onAccess(!isResourceSafe())) {
1047         m_context->synthesizeGLError(GraphicsContext3D::INVALID_FRAMEBUFFER_OPERATION);
1048         return;
1049     }
1050     clearIfComposited();
1051     if (isResourceSafe())
1052         m_context->copyTexImage2D(target, level, internalformat, x, y, width, height, border);
1053     else {
1054         GC3Dint clippedX, clippedY;
1055         GC3Dsizei clippedWidth, clippedHeight;
1056         if (clip2D(x, y, width, height, getBoundFramebufferWidth(), getBoundFramebufferHeight(), &clippedX, &clippedY, &clippedWidth, &clippedHeight)) {
1057             m_context->texImage2DResourceSafe(target, level, internalformat, width, height, border,
1058                                               internalformat, GraphicsContext3D::UNSIGNED_BYTE, m_unpackAlignment);
1059             if (clippedWidth > 0 && clippedHeight > 0) {
1060                 m_context->copyTexSubImage2D(target, level, clippedX - x, clippedY - y,
1061                                              clippedX, clippedY, clippedWidth, clippedHeight);
1062             }
1063         } else
1064             m_context->copyTexImage2D(target, level, internalformat, x, y, width, height, border);
1065     }
1066     // FIXME: if the framebuffer is not complete, none of the below should be executed.
1067     tex->setLevelInfo(target, level, internalformat, width, height, GraphicsContext3D::UNSIGNED_BYTE);
1068     cleanupAfterGraphicsCall(false);
1069 }
1070 
copyTexSubImage2D(GC3Denum target,GC3Dint level,GC3Dint xoffset,GC3Dint yoffset,GC3Dint x,GC3Dint y,GC3Dsizei width,GC3Dsizei height)1071 void WebGLRenderingContext::copyTexSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height)
1072 {
1073     if (isContextLost())
1074         return;
1075     if (!validateTexFuncLevel(target, level))
1076         return;
1077     WebGLTexture* tex = validateTextureBinding(target, true);
1078     if (!tex)
1079         return;
1080     if (!validateSize(xoffset, yoffset) || !validateSize(width, height))
1081         return;
1082     if (xoffset + width > tex->getWidth(target, level) || yoffset + height > tex->getHeight(target, level)) {
1083         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
1084         return;
1085     }
1086     if (!isTexInternalFormatColorBufferCombinationValid(tex->getInternalFormat(target, level), getBoundFramebufferColorFormat())) {
1087         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
1088         return;
1089     }
1090     if (m_framebufferBinding && !m_framebufferBinding->onAccess(!isResourceSafe())) {
1091         m_context->synthesizeGLError(GraphicsContext3D::INVALID_FRAMEBUFFER_OPERATION);
1092         return;
1093     }
1094     clearIfComposited();
1095     if (isResourceSafe())
1096         m_context->copyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height);
1097     else {
1098         GC3Dint clippedX, clippedY;
1099         GC3Dsizei clippedWidth, clippedHeight;
1100         if (clip2D(x, y, width, height, getBoundFramebufferWidth(), getBoundFramebufferHeight(), &clippedX, &clippedY, &clippedWidth, &clippedHeight)) {
1101             GC3Denum format = tex->getInternalFormat(target, level);
1102             GC3Denum type = tex->getType(target, level);
1103             OwnArrayPtr<unsigned char> zero;
1104             if (width && height) {
1105                 unsigned int size;
1106                 GC3Denum error = m_context->computeImageSizeInBytes(format, type, width, height, m_unpackAlignment, &size, 0);
1107                 if (error != GraphicsContext3D::NO_ERROR) {
1108                     m_context->synthesizeGLError(error);
1109                     return;
1110                 }
1111                 zero = adoptArrayPtr(new unsigned char[size]);
1112                 if (!zero) {
1113                     m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
1114                     return;
1115                 }
1116                 memset(zero.get(), 0, size);
1117             }
1118             m_context->texSubImage2D(target, level, xoffset, yoffset, width, height, format, type, zero.get());
1119             if (clippedWidth > 0 && clippedHeight > 0) {
1120                 m_context->copyTexSubImage2D(target, level, xoffset + clippedX - x, yoffset + clippedY - y,
1121                                              clippedX, clippedY, clippedWidth, clippedHeight);
1122             }
1123         } else
1124             m_context->copyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height);
1125     }
1126     cleanupAfterGraphicsCall(false);
1127 }
1128 
createBuffer()1129 PassRefPtr<WebGLBuffer> WebGLRenderingContext::createBuffer()
1130 {
1131     if (isContextLost())
1132         return 0;
1133     RefPtr<WebGLBuffer> o = WebGLBuffer::create(this);
1134     addObject(o.get());
1135     return o;
1136 }
1137 
createFramebuffer()1138 PassRefPtr<WebGLFramebuffer> WebGLRenderingContext::createFramebuffer()
1139 {
1140     if (isContextLost())
1141         return 0;
1142     RefPtr<WebGLFramebuffer> o = WebGLFramebuffer::create(this);
1143     addObject(o.get());
1144     return o;
1145 }
1146 
createTexture()1147 PassRefPtr<WebGLTexture> WebGLRenderingContext::createTexture()
1148 {
1149     if (isContextLost())
1150         return 0;
1151     RefPtr<WebGLTexture> o = WebGLTexture::create(this);
1152     addObject(o.get());
1153     return o;
1154 }
1155 
createProgram()1156 PassRefPtr<WebGLProgram> WebGLRenderingContext::createProgram()
1157 {
1158     if (isContextLost())
1159         return 0;
1160     RefPtr<WebGLProgram> o = WebGLProgram::create(this);
1161     addObject(o.get());
1162     return o;
1163 }
1164 
createRenderbuffer()1165 PassRefPtr<WebGLRenderbuffer> WebGLRenderingContext::createRenderbuffer()
1166 {
1167     if (isContextLost())
1168         return 0;
1169     RefPtr<WebGLRenderbuffer> o = WebGLRenderbuffer::create(this);
1170     addObject(o.get());
1171     return o;
1172 }
1173 
createShader(GC3Denum type,ExceptionCode & ec)1174 PassRefPtr<WebGLShader> WebGLRenderingContext::createShader(GC3Denum type, ExceptionCode& ec)
1175 {
1176     UNUSED_PARAM(ec);
1177     if (isContextLost())
1178         return 0;
1179     if (type != GraphicsContext3D::VERTEX_SHADER && type != GraphicsContext3D::FRAGMENT_SHADER) {
1180         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
1181         return 0;
1182     }
1183 
1184     RefPtr<WebGLShader> o = WebGLShader::create(this, type);
1185     addObject(o.get());
1186     return o;
1187 }
1188 
cullFace(GC3Denum mode)1189 void WebGLRenderingContext::cullFace(GC3Denum mode)
1190 {
1191     if (isContextLost())
1192         return;
1193     m_context->cullFace(mode);
1194     cleanupAfterGraphicsCall(false);
1195 }
1196 
deleteObject(WebGLObject * object)1197 bool WebGLRenderingContext::deleteObject(WebGLObject* object)
1198 {
1199     if (isContextLost() || !object)
1200         return false;
1201     if (object->context() != this) {
1202         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
1203         return false;
1204     }
1205     if (object->object())
1206         object->deleteObject();
1207     return true;
1208 }
1209 
deleteBuffer(WebGLBuffer * buffer)1210 void WebGLRenderingContext::deleteBuffer(WebGLBuffer* buffer)
1211 {
1212     if (!deleteObject(buffer))
1213         return;
1214     if (m_boundArrayBuffer == buffer)
1215         m_boundArrayBuffer = 0;
1216     RefPtr<WebGLBuffer> elementArrayBuffer = m_boundVertexArrayObject->getElementArrayBuffer();
1217     if (elementArrayBuffer == buffer)
1218         m_boundVertexArrayObject->setElementArrayBuffer(0);
1219     if (!isGLES2Compliant()) {
1220         WebGLVertexArrayObjectOES::VertexAttribState& state = m_boundVertexArrayObject->getVertexAttribState(0);
1221         if (buffer == state.bufferBinding) {
1222             state.bufferBinding = m_vertexAttrib0Buffer;
1223             state.bytesPerElement = 0;
1224             state.size = 4;
1225             state.type = GraphicsContext3D::FLOAT;
1226             state.normalized = false;
1227             state.stride = 16;
1228             state.originalStride = 0;
1229             state.offset = 0;
1230         }
1231     }
1232 }
1233 
deleteFramebuffer(WebGLFramebuffer * framebuffer)1234 void WebGLRenderingContext::deleteFramebuffer(WebGLFramebuffer* framebuffer)
1235 {
1236     if (!deleteObject(framebuffer))
1237         return;
1238     if (framebuffer == m_framebufferBinding) {
1239         m_framebufferBinding = 0;
1240         // Have to call bindFramebuffer here to bind back to internal fbo.
1241         m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, 0);
1242     }
1243 }
1244 
deleteProgram(WebGLProgram * program)1245 void WebGLRenderingContext::deleteProgram(WebGLProgram* program)
1246 {
1247     deleteObject(program);
1248     // We don't reset m_currentProgram to 0 here because the deletion of the
1249     // current program is delayed.
1250 }
1251 
deleteRenderbuffer(WebGLRenderbuffer * renderbuffer)1252 void WebGLRenderingContext::deleteRenderbuffer(WebGLRenderbuffer* renderbuffer)
1253 {
1254     if (!deleteObject(renderbuffer))
1255         return;
1256     if (renderbuffer == m_renderbufferBinding)
1257         m_renderbufferBinding = 0;
1258     if (m_framebufferBinding)
1259         m_framebufferBinding->removeAttachment(renderbuffer);
1260 }
1261 
deleteShader(WebGLShader * shader)1262 void WebGLRenderingContext::deleteShader(WebGLShader* shader)
1263 {
1264     deleteObject(shader);
1265 }
1266 
deleteTexture(WebGLTexture * texture)1267 void WebGLRenderingContext::deleteTexture(WebGLTexture* texture)
1268 {
1269     if (!deleteObject(texture))
1270         return;
1271     for (size_t i = 0; i < m_textureUnits.size(); ++i) {
1272         if (texture == m_textureUnits[i].m_texture2DBinding)
1273             m_textureUnits[i].m_texture2DBinding = 0;
1274         if (texture == m_textureUnits[i].m_textureCubeMapBinding)
1275             m_textureUnits[i].m_textureCubeMapBinding = 0;
1276     }
1277     if (m_framebufferBinding)
1278         m_framebufferBinding->removeAttachment(texture);
1279 }
1280 
depthFunc(GC3Denum func)1281 void WebGLRenderingContext::depthFunc(GC3Denum func)
1282 {
1283     if (isContextLost())
1284         return;
1285     m_context->depthFunc(func);
1286     cleanupAfterGraphicsCall(false);
1287 }
1288 
depthMask(GC3Dboolean flag)1289 void WebGLRenderingContext::depthMask(GC3Dboolean flag)
1290 {
1291     if (isContextLost())
1292         return;
1293     m_context->depthMask(flag);
1294     cleanupAfterGraphicsCall(false);
1295 }
1296 
depthRange(GC3Dfloat zNear,GC3Dfloat zFar)1297 void WebGLRenderingContext::depthRange(GC3Dfloat zNear, GC3Dfloat zFar)
1298 {
1299     if (isContextLost())
1300         return;
1301     if (zNear > zFar) {
1302         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
1303         return;
1304     }
1305     m_context->depthRange(zNear, zFar);
1306     cleanupAfterGraphicsCall(false);
1307 }
1308 
detachShader(WebGLProgram * program,WebGLShader * shader,ExceptionCode & ec)1309 void WebGLRenderingContext::detachShader(WebGLProgram* program, WebGLShader* shader, ExceptionCode& ec)
1310 {
1311     UNUSED_PARAM(ec);
1312     if (isContextLost() || !validateWebGLObject(program) || !validateWebGLObject(shader))
1313         return;
1314     if (!program->detachShader(shader)) {
1315         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
1316         return;
1317     }
1318     m_context->detachShader(objectOrZero(program), objectOrZero(shader));
1319     shader->onDetached();
1320     cleanupAfterGraphicsCall(false);
1321 }
1322 
disable(GC3Denum cap)1323 void WebGLRenderingContext::disable(GC3Denum cap)
1324 {
1325     if (isContextLost() || !validateCapability(cap))
1326         return;
1327     if (cap == GraphicsContext3D::SCISSOR_TEST)
1328         m_scissorEnabled = false;
1329     m_context->disable(cap);
1330     cleanupAfterGraphicsCall(false);
1331 }
1332 
disableVertexAttribArray(GC3Duint index,ExceptionCode & ec)1333 void WebGLRenderingContext::disableVertexAttribArray(GC3Duint index, ExceptionCode& ec)
1334 {
1335     UNUSED_PARAM(ec);
1336     if (isContextLost())
1337         return;
1338     if (index >= m_maxVertexAttribs) {
1339         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
1340         return;
1341     }
1342 
1343     WebGLVertexArrayObjectOES::VertexAttribState& state = m_boundVertexArrayObject->getVertexAttribState(index);
1344     state.enabled = false;
1345 
1346     if (index > 0 || isGLES2Compliant()) {
1347         m_context->disableVertexAttribArray(index);
1348         cleanupAfterGraphicsCall(false);
1349     }
1350 }
1351 
validateElementArraySize(GC3Dsizei count,GC3Denum type,GC3Dintptr offset)1352 bool WebGLRenderingContext::validateElementArraySize(GC3Dsizei count, GC3Denum type, GC3Dintptr offset)
1353 {
1354     RefPtr<WebGLBuffer> elementArrayBuffer = m_boundVertexArrayObject->getElementArrayBuffer();
1355 
1356     if (!elementArrayBuffer)
1357         return false;
1358 
1359     if (offset < 0)
1360         return false;
1361 
1362     if (type == GraphicsContext3D::UNSIGNED_SHORT) {
1363         // For an unsigned short array, offset must be divisible by 2 for alignment reasons.
1364         if (offset % 2)
1365             return false;
1366 
1367         // Make uoffset an element offset.
1368         offset /= 2;
1369 
1370         GC3Dsizeiptr n = elementArrayBuffer->byteLength() / 2;
1371         if (offset > n || count > n - offset)
1372             return false;
1373     } else if (type == GraphicsContext3D::UNSIGNED_BYTE) {
1374         GC3Dsizeiptr n = elementArrayBuffer->byteLength();
1375         if (offset > n || count > n - offset)
1376             return false;
1377     }
1378     return true;
1379 }
1380 
validateIndexArrayConservative(GC3Denum type,int & numElementsRequired)1381 bool WebGLRenderingContext::validateIndexArrayConservative(GC3Denum type, int& numElementsRequired)
1382 {
1383     // Performs conservative validation by caching a maximum index of
1384     // the given type per element array buffer. If all of the bound
1385     // array buffers have enough elements to satisfy that maximum
1386     // index, skips the expensive per-draw-call iteration in
1387     // validateIndexArrayPrecise.
1388 
1389     RefPtr<WebGLBuffer> elementArrayBuffer = m_boundVertexArrayObject->getElementArrayBuffer();
1390 
1391     if (!elementArrayBuffer)
1392         return false;
1393 
1394     GC3Dsizeiptr numElements = elementArrayBuffer->byteLength();
1395     // The case count==0 is already dealt with in drawElements before validateIndexArrayConservative.
1396     if (!numElements)
1397         return false;
1398     const ArrayBuffer* buffer = elementArrayBuffer->elementArrayBuffer();
1399     ASSERT(buffer);
1400 
1401     int maxIndex = elementArrayBuffer->getCachedMaxIndex(type);
1402     if (maxIndex < 0) {
1403         // Compute the maximum index in the entire buffer for the given type of index.
1404         switch (type) {
1405         case GraphicsContext3D::UNSIGNED_BYTE: {
1406             const GC3Dubyte* p = static_cast<const GC3Dubyte*>(buffer->data());
1407             for (GC3Dsizeiptr i = 0; i < numElements; i++)
1408                 maxIndex = max(maxIndex, static_cast<int>(p[i]));
1409             break;
1410         }
1411         case GraphicsContext3D::UNSIGNED_SHORT: {
1412             numElements /= sizeof(GC3Dushort);
1413             const GC3Dushort* p = static_cast<const GC3Dushort*>(buffer->data());
1414             for (GC3Dsizeiptr i = 0; i < numElements; i++)
1415                 maxIndex = max(maxIndex, static_cast<int>(p[i]));
1416             break;
1417         }
1418         default:
1419             return false;
1420         }
1421         elementArrayBuffer->setCachedMaxIndex(type, maxIndex);
1422     }
1423 
1424     if (maxIndex >= 0) {
1425         // The number of required elements is one more than the maximum
1426         // index that will be accessed.
1427         numElementsRequired = maxIndex + 1;
1428         return true;
1429     }
1430 
1431     return false;
1432 }
1433 
validateIndexArrayPrecise(GC3Dsizei count,GC3Denum type,GC3Dintptr offset,int & numElementsRequired)1434 bool WebGLRenderingContext::validateIndexArrayPrecise(GC3Dsizei count, GC3Denum type, GC3Dintptr offset, int& numElementsRequired)
1435 {
1436     ASSERT(count >= 0 && offset >= 0);
1437     int lastIndex = -1;
1438 
1439     RefPtr<WebGLBuffer> elementArrayBuffer = m_boundVertexArrayObject->getElementArrayBuffer();
1440 
1441     if (!elementArrayBuffer)
1442         return false;
1443 
1444     if (!count) {
1445         numElementsRequired = 0;
1446         return true;
1447     }
1448 
1449     if (!elementArrayBuffer->elementArrayBuffer())
1450         return false;
1451 
1452     unsigned long uoffset = offset;
1453     unsigned long n = count;
1454 
1455     if (type == GraphicsContext3D::UNSIGNED_SHORT) {
1456         // Make uoffset an element offset.
1457         uoffset /= sizeof(GC3Dushort);
1458         const GC3Dushort* p = static_cast<const GC3Dushort*>(elementArrayBuffer->elementArrayBuffer()->data()) + uoffset;
1459         while (n-- > 0) {
1460             if (*p > lastIndex)
1461                 lastIndex = *p;
1462             ++p;
1463         }
1464     } else if (type == GraphicsContext3D::UNSIGNED_BYTE) {
1465         const GC3Dubyte* p = static_cast<const GC3Dubyte*>(elementArrayBuffer->elementArrayBuffer()->data()) + uoffset;
1466         while (n-- > 0) {
1467             if (*p > lastIndex)
1468                 lastIndex = *p;
1469             ++p;
1470         }
1471     }
1472 
1473     // Then set the last index in the index array and make sure it is valid.
1474     numElementsRequired = lastIndex + 1;
1475     return numElementsRequired > 0;
1476 }
1477 
validateRenderingState(int numElementsRequired)1478 bool WebGLRenderingContext::validateRenderingState(int numElementsRequired)
1479 {
1480     if (!m_currentProgram)
1481         return false;
1482 
1483     // Look in each enabled vertex attrib and check if they've been bound to a buffer.
1484     for (unsigned i = 0; i < m_maxVertexAttribs; ++i) {
1485         const WebGLVertexArrayObjectOES::VertexAttribState& state = m_boundVertexArrayObject->getVertexAttribState(i);
1486         if (state.enabled
1487             && (!state.bufferBinding || !state.bufferBinding->object()))
1488             return false;
1489     }
1490 
1491     if (numElementsRequired <= 0)
1492         return true;
1493 
1494     // Look in each consumed vertex attrib (by the current program) and find the smallest buffer size
1495     int smallestNumElements = INT_MAX;
1496     int numActiveAttribLocations = m_currentProgram->numActiveAttribLocations();
1497     for (int i = 0; i < numActiveAttribLocations; ++i) {
1498         int loc = m_currentProgram->getActiveAttribLocation(i);
1499         if (loc >= 0 && loc < static_cast<int>(m_maxVertexAttribs)) {
1500             const WebGLVertexArrayObjectOES::VertexAttribState& state = m_boundVertexArrayObject->getVertexAttribState(loc);
1501             if (state.enabled) {
1502                 // Avoid off-by-one errors in numElements computation.
1503                 // For the last element, we will only touch the data for the
1504                 // element and nothing beyond it.
1505                 int bytesRemaining = static_cast<int>(state.bufferBinding->byteLength() - state.offset);
1506                 int numElements = 0;
1507                 ASSERT(state.stride > 0);
1508                 if (bytesRemaining >= state.bytesPerElement)
1509                     numElements = 1 + (bytesRemaining - state.bytesPerElement) / state.stride;
1510                 if (numElements < smallestNumElements)
1511                     smallestNumElements = numElements;
1512             }
1513         }
1514     }
1515 
1516     if (smallestNumElements == INT_MAX)
1517         smallestNumElements = 0;
1518 
1519     return numElementsRequired <= smallestNumElements;
1520 }
1521 
validateWebGLObject(WebGLObject * object)1522 bool WebGLRenderingContext::validateWebGLObject(WebGLObject* object)
1523 {
1524     if (!object || !object->object()) {
1525         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
1526         return false;
1527     }
1528     if (object->context() != this) {
1529         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
1530         return false;
1531     }
1532     return true;
1533 }
1534 
drawArrays(GC3Denum mode,GC3Dint first,GC3Dsizei count,ExceptionCode & ec)1535 void WebGLRenderingContext::drawArrays(GC3Denum mode, GC3Dint first, GC3Dsizei count, ExceptionCode& ec)
1536 {
1537     UNUSED_PARAM(ec);
1538 
1539     if (isContextLost() || !validateDrawMode(mode))
1540         return;
1541 
1542     if (!validateStencilSettings())
1543         return;
1544 
1545     if (first < 0 || count < 0) {
1546         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
1547         return;
1548     }
1549 
1550     if (!count)
1551         return;
1552 
1553     if (!isErrorGeneratedOnOutOfBoundsAccesses()) {
1554         // Ensure we have a valid rendering state
1555         CheckedInt<GC3Dint> checkedFirst(first);
1556         CheckedInt<GC3Dint> checkedCount(count);
1557         CheckedInt<GC3Dint> checkedSum = checkedFirst + checkedCount;
1558         if (!checkedSum.valid() || !validateRenderingState(checkedSum.value())) {
1559             m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
1560             return;
1561         }
1562     } else {
1563         if (!validateRenderingState(0)) {
1564             m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
1565             return;
1566         }
1567     }
1568 
1569     if (m_framebufferBinding && !m_framebufferBinding->onAccess(!isResourceSafe())) {
1570         m_context->synthesizeGLError(GraphicsContext3D::INVALID_FRAMEBUFFER_OPERATION);
1571         return;
1572     }
1573 
1574     clearIfComposited();
1575 
1576     bool vertexAttrib0Simulated = false;
1577     if (!isGLES2Compliant())
1578         vertexAttrib0Simulated = simulateVertexAttrib0(first + count - 1);
1579     if (!isGLES2NPOTStrict())
1580         handleNPOTTextures(true);
1581     m_context->drawArrays(mode, first, count);
1582     if (!isGLES2Compliant() && vertexAttrib0Simulated)
1583         restoreStatesAfterVertexAttrib0Simulation();
1584     if (!isGLES2NPOTStrict())
1585         handleNPOTTextures(false);
1586     cleanupAfterGraphicsCall(true);
1587 }
1588 
drawElements(GC3Denum mode,GC3Dsizei count,GC3Denum type,GC3Dintptr offset,ExceptionCode & ec)1589 void WebGLRenderingContext::drawElements(GC3Denum mode, GC3Dsizei count, GC3Denum type, GC3Dintptr offset, ExceptionCode& ec)
1590 {
1591     UNUSED_PARAM(ec);
1592 
1593     if (isContextLost() || !validateDrawMode(mode))
1594         return;
1595 
1596     if (!validateStencilSettings())
1597         return;
1598 
1599     switch (type) {
1600     case GraphicsContext3D::UNSIGNED_BYTE:
1601     case GraphicsContext3D::UNSIGNED_SHORT:
1602         break;
1603     default:
1604         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
1605         return;
1606     }
1607 
1608     if (count < 0 || offset < 0) {
1609         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
1610         return;
1611     }
1612 
1613     if (!count)
1614         return;
1615 
1616     if (!m_boundVertexArrayObject->getElementArrayBuffer()) {
1617         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
1618         return;
1619     }
1620 
1621     int numElements = 0;
1622     if (!isErrorGeneratedOnOutOfBoundsAccesses()) {
1623         // Ensure we have a valid rendering state
1624         if (!validateElementArraySize(count, type, offset)) {
1625             m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
1626             return;
1627         }
1628         if (!count)
1629             return;
1630         if (!validateIndexArrayConservative(type, numElements) || !validateRenderingState(numElements)) {
1631             if (!validateIndexArrayPrecise(count, type, offset, numElements) || !validateRenderingState(numElements)) {
1632                 m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
1633                 return;
1634             }
1635         }
1636     } else {
1637         if (!validateRenderingState(0)) {
1638             m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
1639             return;
1640         }
1641     }
1642 
1643     if (m_framebufferBinding && !m_framebufferBinding->onAccess(!isResourceSafe())) {
1644         m_context->synthesizeGLError(GraphicsContext3D::INVALID_FRAMEBUFFER_OPERATION);
1645         return;
1646     }
1647     clearIfComposited();
1648 
1649     bool vertexAttrib0Simulated = false;
1650     if (!isGLES2Compliant()) {
1651         if (!numElements)
1652             validateIndexArrayPrecise(count, type, offset, numElements);
1653         vertexAttrib0Simulated = simulateVertexAttrib0(numElements);
1654     }
1655     if (!isGLES2NPOTStrict())
1656         handleNPOTTextures(true);
1657     m_context->drawElements(mode, count, type, offset);
1658     if (!isGLES2Compliant() && vertexAttrib0Simulated)
1659         restoreStatesAfterVertexAttrib0Simulation();
1660     if (!isGLES2NPOTStrict())
1661         handleNPOTTextures(false);
1662     cleanupAfterGraphicsCall(true);
1663 }
1664 
enable(GC3Denum cap)1665 void WebGLRenderingContext::enable(GC3Denum cap)
1666 {
1667     if (isContextLost() || !validateCapability(cap))
1668         return;
1669     if (cap == GraphicsContext3D::SCISSOR_TEST)
1670         m_scissorEnabled = true;
1671     m_context->enable(cap);
1672     cleanupAfterGraphicsCall(false);
1673 }
1674 
enableVertexAttribArray(GC3Duint index,ExceptionCode & ec)1675 void WebGLRenderingContext::enableVertexAttribArray(GC3Duint index, ExceptionCode& ec)
1676 {
1677     UNUSED_PARAM(ec);
1678     if (isContextLost())
1679         return;
1680     if (index >= m_maxVertexAttribs) {
1681         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
1682         return;
1683     }
1684 
1685     WebGLVertexArrayObjectOES::VertexAttribState& state = m_boundVertexArrayObject->getVertexAttribState(index);
1686     state.enabled = true;
1687 
1688     m_context->enableVertexAttribArray(index);
1689     cleanupAfterGraphicsCall(false);
1690 }
1691 
finish()1692 void WebGLRenderingContext::finish()
1693 {
1694     if (isContextLost())
1695         return;
1696     m_context->finish();
1697     cleanupAfterGraphicsCall(false);
1698 }
1699 
flush()1700 void WebGLRenderingContext::flush()
1701 {
1702     if (isContextLost())
1703         return;
1704     m_context->flush();
1705     cleanupAfterGraphicsCall(false);
1706 }
1707 
framebufferRenderbuffer(GC3Denum target,GC3Denum attachment,GC3Denum renderbuffertarget,WebGLRenderbuffer * buffer,ExceptionCode & ec)1708 void WebGLRenderingContext::framebufferRenderbuffer(GC3Denum target, GC3Denum attachment, GC3Denum renderbuffertarget, WebGLRenderbuffer* buffer, ExceptionCode& ec)
1709 {
1710     UNUSED_PARAM(ec);
1711     if (isContextLost() || !validateFramebufferFuncParameters(target, attachment))
1712         return;
1713     if (renderbuffertarget != GraphicsContext3D::RENDERBUFFER) {
1714         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
1715         return;
1716     }
1717     if (buffer && buffer->context() != this) {
1718         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
1719         return;
1720     }
1721     // Don't allow the default framebuffer to be mutated; all current
1722     // implementations use an FBO internally in place of the default
1723     // FBO.
1724     if (!m_framebufferBinding || !m_framebufferBinding->object()) {
1725         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
1726         return;
1727     }
1728     Platform3DObject bufferObject = objectOrZero(buffer);
1729     bool reattachDepth = false;
1730     bool reattachStencil = false;
1731     bool reattachDepthStencilDepth = false;
1732     bool reattachDepthStencilStencil = false;
1733     switch (attachment) {
1734     case GraphicsContext3D::DEPTH_STENCIL_ATTACHMENT:
1735         m_context->framebufferRenderbuffer(target, GraphicsContext3D::DEPTH_ATTACHMENT, renderbuffertarget, bufferObject);
1736         m_context->framebufferRenderbuffer(target, GraphicsContext3D::STENCIL_ATTACHMENT, renderbuffertarget, bufferObject);
1737         if (!bufferObject) {
1738             reattachDepth = true;
1739             reattachStencil = true;
1740         }
1741         break;
1742     case GraphicsContext3D::DEPTH_ATTACHMENT:
1743         m_context->framebufferRenderbuffer(target, attachment, renderbuffertarget, objectOrZero(buffer));
1744         if (!bufferObject)
1745             reattachDepthStencilDepth = true;
1746         break;
1747     case GraphicsContext3D::STENCIL_ATTACHMENT:
1748         m_context->framebufferRenderbuffer(target, attachment, renderbuffertarget, objectOrZero(buffer));
1749         if (!bufferObject)
1750             reattachDepthStencilStencil = true;
1751         break;
1752     default:
1753         m_context->framebufferRenderbuffer(target, attachment, renderbuffertarget, objectOrZero(buffer));
1754     }
1755     m_framebufferBinding->setAttachment(attachment, buffer);
1756     if (reattachDepth) {
1757         Platform3DObject object = objectOrZero(m_framebufferBinding->getAttachment(GraphicsContext3D::DEPTH_ATTACHMENT));
1758         if (object)
1759             m_context->framebufferRenderbuffer(target, GraphicsContext3D::DEPTH_ATTACHMENT, renderbuffertarget, object);
1760     }
1761     if (reattachStencil) {
1762         Platform3DObject object = objectOrZero(m_framebufferBinding->getAttachment(GraphicsContext3D::STENCIL_ATTACHMENT));
1763         if (object)
1764             m_context->framebufferRenderbuffer(target, GraphicsContext3D::STENCIL_ATTACHMENT, renderbuffertarget, object);
1765     }
1766     if (reattachDepthStencilDepth) {
1767         Platform3DObject object = objectOrZero(m_framebufferBinding->getAttachment(GraphicsContext3D::DEPTH_STENCIL_ATTACHMENT));
1768         if (object)
1769             m_context->framebufferRenderbuffer(target, GraphicsContext3D::DEPTH_ATTACHMENT, renderbuffertarget, object);
1770     }
1771     if (reattachDepthStencilStencil) {
1772         Platform3DObject object = objectOrZero(m_framebufferBinding->getAttachment(GraphicsContext3D::DEPTH_STENCIL_ATTACHMENT));
1773         if (object)
1774             m_context->framebufferRenderbuffer(target, GraphicsContext3D::STENCIL_ATTACHMENT, renderbuffertarget, object);
1775     }
1776     cleanupAfterGraphicsCall(false);
1777 }
1778 
framebufferTexture2D(GC3Denum target,GC3Denum attachment,GC3Denum textarget,WebGLTexture * texture,GC3Dint level,ExceptionCode & ec)1779 void WebGLRenderingContext::framebufferTexture2D(GC3Denum target, GC3Denum attachment, GC3Denum textarget, WebGLTexture* texture, GC3Dint level, ExceptionCode& ec)
1780 {
1781     UNUSED_PARAM(ec);
1782     if (isContextLost() || !validateFramebufferFuncParameters(target, attachment))
1783         return;
1784     if (level) {
1785         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
1786         return;
1787     }
1788     if (texture && texture->context() != this) {
1789         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
1790         return;
1791     }
1792     // Don't allow the default framebuffer to be mutated; all current
1793     // implementations use an FBO internally in place of the default
1794     // FBO.
1795     if (!m_framebufferBinding || !m_framebufferBinding->object()) {
1796         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
1797         return;
1798     }
1799     m_context->framebufferTexture2D(target, attachment, textarget, objectOrZero(texture), level);
1800     m_framebufferBinding->setAttachment(attachment, textarget, texture, level);
1801     cleanupAfterGraphicsCall(false);
1802 }
1803 
frontFace(GC3Denum mode)1804 void WebGLRenderingContext::frontFace(GC3Denum mode)
1805 {
1806     if (isContextLost())
1807         return;
1808     m_context->frontFace(mode);
1809     cleanupAfterGraphicsCall(false);
1810 }
1811 
generateMipmap(GC3Denum target)1812 void WebGLRenderingContext::generateMipmap(GC3Denum target)
1813 {
1814     if (isContextLost())
1815         return;
1816     WebGLTexture* tex = validateTextureBinding(target, false);
1817     if (!tex)
1818         return;
1819     if (!tex->canGenerateMipmaps()) {
1820         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
1821         return;
1822     }
1823     // generateMipmap won't work properly if minFilter is not NEAREST_MIPMAP_LINEAR
1824     // on Mac.  Remove the hack once this driver bug is fixed.
1825 #if OS(DARWIN)
1826     bool needToResetMinFilter = false;
1827     if (tex->getMinFilter() != GraphicsContext3D::NEAREST_MIPMAP_LINEAR) {
1828         m_context->texParameteri(target, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::NEAREST_MIPMAP_LINEAR);
1829         needToResetMinFilter = true;
1830     }
1831 #endif
1832     m_context->generateMipmap(target);
1833 #if OS(DARWIN)
1834     if (needToResetMinFilter)
1835         m_context->texParameteri(target, GraphicsContext3D::TEXTURE_MIN_FILTER, tex->getMinFilter());
1836 #endif
1837     tex->generateMipmapLevelInfo();
1838     cleanupAfterGraphicsCall(false);
1839 }
1840 
getActiveAttrib(WebGLProgram * program,GC3Duint index,ExceptionCode & ec)1841 PassRefPtr<WebGLActiveInfo> WebGLRenderingContext::getActiveAttrib(WebGLProgram* program, GC3Duint index, ExceptionCode& ec)
1842 {
1843     UNUSED_PARAM(ec);
1844     if (isContextLost() || !validateWebGLObject(program))
1845         return 0;
1846     ActiveInfo info;
1847     if (!m_context->getActiveAttrib(objectOrZero(program), index, info))
1848         return 0;
1849     return WebGLActiveInfo::create(info.name, info.type, info.size);
1850 }
1851 
getActiveUniform(WebGLProgram * program,GC3Duint index,ExceptionCode & ec)1852 PassRefPtr<WebGLActiveInfo> WebGLRenderingContext::getActiveUniform(WebGLProgram* program, GC3Duint index, ExceptionCode& ec)
1853 {
1854     UNUSED_PARAM(ec);
1855     if (isContextLost() || !validateWebGLObject(program))
1856         return 0;
1857     ActiveInfo info;
1858     if (!m_context->getActiveUniform(objectOrZero(program), index, info))
1859         return 0;
1860     if (!isGLES2Compliant())
1861         if (info.size > 1 && !info.name.endsWith("[0]"))
1862             info.name.append("[0]");
1863     return WebGLActiveInfo::create(info.name, info.type, info.size);
1864 }
1865 
getAttachedShaders(WebGLProgram * program,Vector<WebGLShader * > & shaderObjects,ExceptionCode & ec)1866 bool WebGLRenderingContext::getAttachedShaders(WebGLProgram* program, Vector<WebGLShader*>& shaderObjects, ExceptionCode& ec)
1867 {
1868     UNUSED_PARAM(ec);
1869     shaderObjects.clear();
1870     if (isContextLost() || !validateWebGLObject(program))
1871         return false;
1872     GC3Dint numShaders = 0;
1873     m_context->getProgramiv(objectOrZero(program), GraphicsContext3D::ATTACHED_SHADERS, &numShaders);
1874     if (numShaders) {
1875         OwnArrayPtr<Platform3DObject> shaders = adoptArrayPtr(new Platform3DObject[numShaders]);
1876         GC3Dsizei count = 0;
1877         m_context->getAttachedShaders(objectOrZero(program), numShaders, &count, shaders.get());
1878         if (count != numShaders)
1879             return false;
1880         shaderObjects.resize(numShaders);
1881         for (GC3Dint ii = 0; ii < numShaders; ++ii) {
1882             WebGLShader* shader = findShader(shaders[ii]);
1883             if (!shader) {
1884                 shaderObjects.clear();
1885                 return false;
1886             }
1887             shaderObjects[ii] = shader;
1888         }
1889     }
1890     return true;
1891 }
1892 
getAttribLocation(WebGLProgram * program,const String & name)1893 GC3Dint WebGLRenderingContext::getAttribLocation(WebGLProgram* program, const String& name)
1894 {
1895     if (isContextLost())
1896         return -1;
1897     if (!validateString(name))
1898         return -1;
1899     return m_context->getAttribLocation(objectOrZero(program), name);
1900 }
1901 
getBufferParameter(GC3Denum target,GC3Denum pname,ExceptionCode & ec)1902 WebGLGetInfo WebGLRenderingContext::getBufferParameter(GC3Denum target, GC3Denum pname, ExceptionCode& ec)
1903 {
1904     UNUSED_PARAM(ec);
1905     if (isContextLost())
1906         return WebGLGetInfo();
1907     if (target != GraphicsContext3D::ARRAY_BUFFER && target != GraphicsContext3D::ELEMENT_ARRAY_BUFFER) {
1908         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
1909         return WebGLGetInfo();
1910     }
1911 
1912     if (pname != GraphicsContext3D::BUFFER_SIZE && pname != GraphicsContext3D::BUFFER_USAGE) {
1913         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
1914         return WebGLGetInfo();
1915     }
1916 
1917     WebGLStateRestorer(this, false);
1918     GC3Dint value = 0;
1919     m_context->getBufferParameteriv(target, pname, &value);
1920     if (pname == GraphicsContext3D::BUFFER_SIZE)
1921         return WebGLGetInfo(value);
1922     return WebGLGetInfo(static_cast<unsigned int>(value));
1923 }
1924 
getContextAttributes()1925 PassRefPtr<WebGLContextAttributes> WebGLRenderingContext::getContextAttributes()
1926 {
1927     if (isContextLost())
1928         return 0;
1929     // We always need to return a new WebGLContextAttributes object to
1930     // prevent the user from mutating any cached version.
1931     return WebGLContextAttributes::create(m_context->getContextAttributes());
1932 }
1933 
getError()1934 GC3Denum WebGLRenderingContext::getError()
1935 {
1936     return m_context->getError();
1937 }
1938 
getExtension(const String & name)1939 WebGLExtension* WebGLRenderingContext::getExtension(const String& name)
1940 {
1941     if (isContextLost())
1942         return 0;
1943 
1944     if (equalIgnoringCase(name, "OES_standard_derivatives")
1945         && m_context->getExtensions()->supports("GL_OES_standard_derivatives")) {
1946         if (!m_oesStandardDerivatives) {
1947             m_context->getExtensions()->ensureEnabled("GL_OES_standard_derivatives");
1948             m_oesStandardDerivatives = OESStandardDerivatives::create();
1949         }
1950         return m_oesStandardDerivatives.get();
1951     }
1952     if (equalIgnoringCase(name, "OES_texture_float")
1953         && m_context->getExtensions()->supports("GL_OES_texture_float")) {
1954         if (!m_oesTextureFloat) {
1955             m_context->getExtensions()->ensureEnabled("GL_OES_texture_float");
1956             m_oesTextureFloat = OESTextureFloat::create();
1957         }
1958         return m_oesTextureFloat.get();
1959     }
1960     if (equalIgnoringCase(name, "OES_vertex_array_object")
1961         && m_context->getExtensions()->supports("GL_OES_vertex_array_object")) {
1962         if (!m_oesVertexArrayObject) {
1963             m_context->getExtensions()->ensureEnabled("GL_OES_vertex_array_object");
1964             m_oesVertexArrayObject = OESVertexArrayObject::create(this);
1965         }
1966         return m_oesVertexArrayObject.get();
1967     }
1968     if (equalIgnoringCase(name, "WEBKIT_lose_context")) {
1969         if (!m_webkitLoseContext)
1970             m_webkitLoseContext = WebKitLoseContext::create(this);
1971         return m_webkitLoseContext.get();
1972     }
1973 
1974     return 0;
1975 }
1976 
getFramebufferAttachmentParameter(GC3Denum target,GC3Denum attachment,GC3Denum pname,ExceptionCode & ec)1977 WebGLGetInfo WebGLRenderingContext::getFramebufferAttachmentParameter(GC3Denum target, GC3Denum attachment, GC3Denum pname, ExceptionCode& ec)
1978 {
1979     UNUSED_PARAM(ec);
1980     if (isContextLost() || !validateFramebufferFuncParameters(target, attachment))
1981         return WebGLGetInfo();
1982     switch (pname) {
1983     case GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
1984     case GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
1985     case GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
1986     case GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
1987         break;
1988     default:
1989         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
1990         return WebGLGetInfo();
1991     }
1992 
1993     if (!m_framebufferBinding || !m_framebufferBinding->object() || m_framebufferBinding->isIncomplete(false)) {
1994         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
1995         return WebGLGetInfo();
1996     }
1997 
1998     if (pname != GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_OBJECT_NAME) {
1999         WebGLStateRestorer(this, false);
2000         GC3Dint value = 0;
2001         m_context->getFramebufferAttachmentParameteriv(target, attachment, pname, &value);
2002         if (pname == GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE)
2003             return WebGLGetInfo(static_cast<unsigned int>(value));
2004         return WebGLGetInfo(value);
2005     }
2006 
2007     WebGLStateRestorer(this, false);
2008     GC3Dint type = 0;
2009     m_context->getFramebufferAttachmentParameteriv(target, attachment, GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &type);
2010     if (!type)
2011         return WebGLGetInfo();
2012     GC3Dint value = 0;
2013     m_context->getFramebufferAttachmentParameteriv(target, attachment, GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, &value);
2014     switch (type) {
2015     case GraphicsContext3D::RENDERBUFFER:
2016         return WebGLGetInfo(PassRefPtr<WebGLRenderbuffer>(findRenderbuffer(static_cast<Platform3DObject>(value))));
2017     case GraphicsContext3D::TEXTURE:
2018         return WebGLGetInfo(PassRefPtr<WebGLTexture>(findTexture(static_cast<Platform3DObject>(value))));
2019     default:
2020         // FIXME: raise exception?
2021         return WebGLGetInfo();
2022     }
2023 }
2024 
getParameter(GC3Denum pname,ExceptionCode & ec)2025 WebGLGetInfo WebGLRenderingContext::getParameter(GC3Denum pname, ExceptionCode& ec)
2026 {
2027     UNUSED_PARAM(ec);
2028     if (isContextLost())
2029         return WebGLGetInfo();
2030     WebGLStateRestorer(this, false);
2031     switch (pname) {
2032     case GraphicsContext3D::ACTIVE_TEXTURE:
2033         return getUnsignedIntParameter(pname);
2034     case GraphicsContext3D::ALIASED_LINE_WIDTH_RANGE:
2035         return getWebGLFloatArrayParameter(pname);
2036     case GraphicsContext3D::ALIASED_POINT_SIZE_RANGE:
2037         return getWebGLFloatArrayParameter(pname);
2038     case GraphicsContext3D::ALPHA_BITS:
2039         return getIntParameter(pname);
2040     case GraphicsContext3D::ARRAY_BUFFER_BINDING:
2041         return WebGLGetInfo(PassRefPtr<WebGLBuffer>(m_boundArrayBuffer));
2042     case GraphicsContext3D::BLEND:
2043         return getBooleanParameter(pname);
2044     case GraphicsContext3D::BLEND_COLOR:
2045         return getWebGLFloatArrayParameter(pname);
2046     case GraphicsContext3D::BLEND_DST_ALPHA:
2047         return getUnsignedIntParameter(pname);
2048     case GraphicsContext3D::BLEND_DST_RGB:
2049         return getUnsignedIntParameter(pname);
2050     case GraphicsContext3D::BLEND_EQUATION_ALPHA:
2051         return getUnsignedIntParameter(pname);
2052     case GraphicsContext3D::BLEND_EQUATION_RGB:
2053         return getUnsignedIntParameter(pname);
2054     case GraphicsContext3D::BLEND_SRC_ALPHA:
2055         return getUnsignedIntParameter(pname);
2056     case GraphicsContext3D::BLEND_SRC_RGB:
2057         return getUnsignedIntParameter(pname);
2058     case GraphicsContext3D::BLUE_BITS:
2059         return getIntParameter(pname);
2060     case GraphicsContext3D::COLOR_CLEAR_VALUE:
2061         return getWebGLFloatArrayParameter(pname);
2062     case GraphicsContext3D::COLOR_WRITEMASK:
2063         return getBooleanArrayParameter(pname);
2064     case GraphicsContext3D::COMPRESSED_TEXTURE_FORMATS:
2065         // Defined as null in the spec
2066         return WebGLGetInfo();
2067     case GraphicsContext3D::CULL_FACE:
2068         return getBooleanParameter(pname);
2069     case GraphicsContext3D::CULL_FACE_MODE:
2070         return getUnsignedIntParameter(pname);
2071     case GraphicsContext3D::CURRENT_PROGRAM:
2072         return WebGLGetInfo(PassRefPtr<WebGLProgram>(m_currentProgram));
2073     case GraphicsContext3D::DEPTH_BITS:
2074         return getIntParameter(pname);
2075     case GraphicsContext3D::DEPTH_CLEAR_VALUE:
2076         return getFloatParameter(pname);
2077     case GraphicsContext3D::DEPTH_FUNC:
2078         return getUnsignedIntParameter(pname);
2079     case GraphicsContext3D::DEPTH_RANGE:
2080         return getWebGLFloatArrayParameter(pname);
2081     case GraphicsContext3D::DEPTH_TEST:
2082         return getBooleanParameter(pname);
2083     case GraphicsContext3D::DEPTH_WRITEMASK:
2084         return getBooleanParameter(pname);
2085     case GraphicsContext3D::DITHER:
2086         return getBooleanParameter(pname);
2087     case GraphicsContext3D::ELEMENT_ARRAY_BUFFER_BINDING:
2088         return WebGLGetInfo(PassRefPtr<WebGLBuffer>(m_boundVertexArrayObject->getElementArrayBuffer()));
2089     case GraphicsContext3D::FRAMEBUFFER_BINDING:
2090         return WebGLGetInfo(PassRefPtr<WebGLFramebuffer>(m_framebufferBinding));
2091     case GraphicsContext3D::FRONT_FACE:
2092         return getUnsignedIntParameter(pname);
2093     case GraphicsContext3D::GENERATE_MIPMAP_HINT:
2094         return getUnsignedIntParameter(pname);
2095     case GraphicsContext3D::GREEN_BITS:
2096         return getIntParameter(pname);
2097     case GraphicsContext3D::LINE_WIDTH:
2098         return getFloatParameter(pname);
2099     case GraphicsContext3D::MAX_COMBINED_TEXTURE_IMAGE_UNITS:
2100         return getIntParameter(pname);
2101     case GraphicsContext3D::MAX_CUBE_MAP_TEXTURE_SIZE:
2102         return getIntParameter(pname);
2103     case GraphicsContext3D::MAX_FRAGMENT_UNIFORM_VECTORS:
2104         return getIntParameter(pname);
2105     case GraphicsContext3D::MAX_RENDERBUFFER_SIZE:
2106         return getIntParameter(pname);
2107     case GraphicsContext3D::MAX_TEXTURE_IMAGE_UNITS:
2108         return getIntParameter(pname);
2109     case GraphicsContext3D::MAX_TEXTURE_SIZE:
2110         return getIntParameter(pname);
2111     case GraphicsContext3D::MAX_VARYING_VECTORS:
2112         return getIntParameter(pname);
2113     case GraphicsContext3D::MAX_VERTEX_ATTRIBS:
2114         return getIntParameter(pname);
2115     case GraphicsContext3D::MAX_VERTEX_TEXTURE_IMAGE_UNITS:
2116         return getIntParameter(pname);
2117     case GraphicsContext3D::MAX_VERTEX_UNIFORM_VECTORS:
2118         return getIntParameter(pname);
2119     case GraphicsContext3D::MAX_VIEWPORT_DIMS:
2120         return getWebGLIntArrayParameter(pname);
2121     case GraphicsContext3D::NUM_COMPRESSED_TEXTURE_FORMATS:
2122         // WebGL 1.0 specifies that there are no compressed texture formats.
2123         return WebGLGetInfo(static_cast<int>(0));
2124     case GraphicsContext3D::NUM_SHADER_BINARY_FORMATS:
2125         // FIXME: should we always return 0 for this?
2126         return getIntParameter(pname);
2127     case GraphicsContext3D::PACK_ALIGNMENT:
2128         return getIntParameter(pname);
2129     case GraphicsContext3D::POLYGON_OFFSET_FACTOR:
2130         return getFloatParameter(pname);
2131     case GraphicsContext3D::POLYGON_OFFSET_FILL:
2132         return getBooleanParameter(pname);
2133     case GraphicsContext3D::POLYGON_OFFSET_UNITS:
2134         return getFloatParameter(pname);
2135     case GraphicsContext3D::RED_BITS:
2136         return getIntParameter(pname);
2137     case GraphicsContext3D::RENDERBUFFER_BINDING:
2138         return WebGLGetInfo(PassRefPtr<WebGLRenderbuffer>(m_renderbufferBinding));
2139     case GraphicsContext3D::RENDERER:
2140         return WebGLGetInfo(m_context->getString(GraphicsContext3D::RENDERER));
2141     case GraphicsContext3D::SAMPLE_BUFFERS:
2142         return getIntParameter(pname);
2143     case GraphicsContext3D::SAMPLE_COVERAGE_INVERT:
2144         return getBooleanParameter(pname);
2145     case GraphicsContext3D::SAMPLE_COVERAGE_VALUE:
2146         return getFloatParameter(pname);
2147     case GraphicsContext3D::SAMPLES:
2148         return getIntParameter(pname);
2149     case GraphicsContext3D::SCISSOR_BOX:
2150         return getWebGLIntArrayParameter(pname);
2151     case GraphicsContext3D::SCISSOR_TEST:
2152         return getBooleanParameter(pname);
2153     case GraphicsContext3D::SHADING_LANGUAGE_VERSION:
2154         return WebGLGetInfo("WebGL GLSL ES 1.0 (" + m_context->getString(GraphicsContext3D::SHADING_LANGUAGE_VERSION) + ")");
2155     case GraphicsContext3D::STENCIL_BACK_FAIL:
2156         return getUnsignedIntParameter(pname);
2157     case GraphicsContext3D::STENCIL_BACK_FUNC:
2158         return getUnsignedIntParameter(pname);
2159     case GraphicsContext3D::STENCIL_BACK_PASS_DEPTH_FAIL:
2160         return getUnsignedIntParameter(pname);
2161     case GraphicsContext3D::STENCIL_BACK_PASS_DEPTH_PASS:
2162         return getUnsignedIntParameter(pname);
2163     case GraphicsContext3D::STENCIL_BACK_REF:
2164         return getIntParameter(pname);
2165     case GraphicsContext3D::STENCIL_BACK_VALUE_MASK:
2166         return getUnsignedIntParameter(pname);
2167     case GraphicsContext3D::STENCIL_BACK_WRITEMASK:
2168         return getUnsignedIntParameter(pname);
2169     case GraphicsContext3D::STENCIL_BITS:
2170         return getIntParameter(pname);
2171     case GraphicsContext3D::STENCIL_CLEAR_VALUE:
2172         return getIntParameter(pname);
2173     case GraphicsContext3D::STENCIL_FAIL:
2174         return getUnsignedIntParameter(pname);
2175     case GraphicsContext3D::STENCIL_FUNC:
2176         return getUnsignedIntParameter(pname);
2177     case GraphicsContext3D::STENCIL_PASS_DEPTH_FAIL:
2178         return getUnsignedIntParameter(pname);
2179     case GraphicsContext3D::STENCIL_PASS_DEPTH_PASS:
2180         return getUnsignedIntParameter(pname);
2181     case GraphicsContext3D::STENCIL_REF:
2182         return getIntParameter(pname);
2183     case GraphicsContext3D::STENCIL_TEST:
2184         return getBooleanParameter(pname);
2185     case GraphicsContext3D::STENCIL_VALUE_MASK:
2186         return getUnsignedIntParameter(pname);
2187     case GraphicsContext3D::STENCIL_WRITEMASK:
2188         return getUnsignedIntParameter(pname);
2189     case GraphicsContext3D::SUBPIXEL_BITS:
2190         return getIntParameter(pname);
2191     case GraphicsContext3D::TEXTURE_BINDING_2D:
2192         return WebGLGetInfo(PassRefPtr<WebGLTexture>(m_textureUnits[m_activeTextureUnit].m_texture2DBinding));
2193     case GraphicsContext3D::TEXTURE_BINDING_CUBE_MAP:
2194         return WebGLGetInfo(PassRefPtr<WebGLTexture>(m_textureUnits[m_activeTextureUnit].m_textureCubeMapBinding));
2195     case GraphicsContext3D::UNPACK_ALIGNMENT:
2196         return getIntParameter(pname);
2197     case GraphicsContext3D::UNPACK_FLIP_Y_WEBGL:
2198         return WebGLGetInfo(m_unpackFlipY);
2199     case GraphicsContext3D::UNPACK_PREMULTIPLY_ALPHA_WEBGL:
2200         return WebGLGetInfo(m_unpackPremultiplyAlpha);
2201     case GraphicsContext3D::UNPACK_COLORSPACE_CONVERSION_WEBGL:
2202         return WebGLGetInfo(m_unpackColorspaceConversion);
2203     case GraphicsContext3D::VENDOR:
2204         return WebGLGetInfo("Webkit (" + m_context->getString(GraphicsContext3D::VENDOR) + ")");
2205     case GraphicsContext3D::VERSION:
2206         return WebGLGetInfo("WebGL 1.0 (" + m_context->getString(GraphicsContext3D::VERSION) + ")");
2207     case GraphicsContext3D::VIEWPORT:
2208         return getWebGLIntArrayParameter(pname);
2209     case Extensions3D::FRAGMENT_SHADER_DERIVATIVE_HINT_OES: // OES_standard_derivatives
2210         if (m_oesStandardDerivatives)
2211             return getUnsignedIntParameter(Extensions3D::FRAGMENT_SHADER_DERIVATIVE_HINT_OES);
2212         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
2213         return WebGLGetInfo();
2214     case Extensions3D::VERTEX_ARRAY_BINDING_OES: // OES_vertex_array_object
2215         if (m_oesVertexArrayObject) {
2216             if (!m_boundVertexArrayObject->isDefaultObject())
2217                 return WebGLGetInfo(PassRefPtr<WebGLVertexArrayObjectOES>(m_boundVertexArrayObject));
2218             return WebGLGetInfo();
2219         }
2220         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
2221         return WebGLGetInfo();
2222     default:
2223         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
2224         return WebGLGetInfo();
2225     }
2226 }
2227 
getProgramParameter(WebGLProgram * program,GC3Denum pname,ExceptionCode & ec)2228 WebGLGetInfo WebGLRenderingContext::getProgramParameter(WebGLProgram* program, GC3Denum pname, ExceptionCode& ec)
2229 {
2230     UNUSED_PARAM(ec);
2231     if (isContextLost() || !validateWebGLObject(program))
2232         return WebGLGetInfo();
2233 
2234     WebGLStateRestorer(this, false);
2235     GC3Dint value = 0;
2236     switch (pname) {
2237     case GraphicsContext3D::DELETE_STATUS:
2238         return WebGLGetInfo(program->isDeleted());
2239     case GraphicsContext3D::VALIDATE_STATUS:
2240         m_context->getProgramiv(objectOrZero(program), pname, &value);
2241         return WebGLGetInfo(static_cast<bool>(value));
2242     case GraphicsContext3D::LINK_STATUS:
2243         return WebGLGetInfo(program->getLinkStatus());
2244     case GraphicsContext3D::ATTACHED_SHADERS:
2245     case GraphicsContext3D::ACTIVE_ATTRIBUTES:
2246     case GraphicsContext3D::ACTIVE_UNIFORMS:
2247         m_context->getProgramiv(objectOrZero(program), pname, &value);
2248         return WebGLGetInfo(value);
2249     default:
2250         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
2251         return WebGLGetInfo();
2252     }
2253 }
2254 
getProgramInfoLog(WebGLProgram * program,ExceptionCode & ec)2255 String WebGLRenderingContext::getProgramInfoLog(WebGLProgram* program, ExceptionCode& ec)
2256 {
2257     UNUSED_PARAM(ec);
2258     if (isContextLost())
2259         return String();
2260     if (!validateWebGLObject(program))
2261         return "";
2262     WebGLStateRestorer(this, false);
2263     return m_context->getProgramInfoLog(objectOrZero(program));
2264 }
2265 
getRenderbufferParameter(GC3Denum target,GC3Denum pname,ExceptionCode & ec)2266 WebGLGetInfo WebGLRenderingContext::getRenderbufferParameter(GC3Denum target, GC3Denum pname, ExceptionCode& ec)
2267 {
2268     UNUSED_PARAM(ec);
2269     if (isContextLost())
2270         return WebGLGetInfo();
2271     if (target != GraphicsContext3D::RENDERBUFFER) {
2272         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
2273         return WebGLGetInfo();
2274     }
2275     if (!m_renderbufferBinding || !m_renderbufferBinding->object()) {
2276         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
2277         return WebGLGetInfo();
2278     }
2279 
2280     if (m_renderbufferBinding->getInternalFormat() == GraphicsContext3D::DEPTH_STENCIL
2281         && !m_renderbufferBinding->isValid()) {
2282         ASSERT(!isDepthStencilSupported());
2283         int value = 0;
2284         switch (pname) {
2285         case GraphicsContext3D::RENDERBUFFER_WIDTH:
2286             value = m_renderbufferBinding->getWidth();
2287             break;
2288         case GraphicsContext3D::RENDERBUFFER_HEIGHT:
2289             value = m_renderbufferBinding->getHeight();
2290             break;
2291         case GraphicsContext3D::RENDERBUFFER_RED_SIZE:
2292         case GraphicsContext3D::RENDERBUFFER_GREEN_SIZE:
2293         case GraphicsContext3D::RENDERBUFFER_BLUE_SIZE:
2294         case GraphicsContext3D::RENDERBUFFER_ALPHA_SIZE:
2295             value = 0;
2296             break;
2297         case GraphicsContext3D::RENDERBUFFER_DEPTH_SIZE:
2298             value = 24;
2299             break;
2300         case GraphicsContext3D::RENDERBUFFER_STENCIL_SIZE:
2301             value = 8;
2302             break;
2303         case GraphicsContext3D::RENDERBUFFER_INTERNAL_FORMAT:
2304             return WebGLGetInfo(m_renderbufferBinding->getInternalFormat());
2305         default:
2306             m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
2307             return WebGLGetInfo();
2308         }
2309         return WebGLGetInfo(value);
2310     }
2311 
2312     WebGLStateRestorer(this, false);
2313     GC3Dint value = 0;
2314     switch (pname) {
2315     case GraphicsContext3D::RENDERBUFFER_WIDTH:
2316     case GraphicsContext3D::RENDERBUFFER_HEIGHT:
2317     case GraphicsContext3D::RENDERBUFFER_RED_SIZE:
2318     case GraphicsContext3D::RENDERBUFFER_GREEN_SIZE:
2319     case GraphicsContext3D::RENDERBUFFER_BLUE_SIZE:
2320     case GraphicsContext3D::RENDERBUFFER_ALPHA_SIZE:
2321     case GraphicsContext3D::RENDERBUFFER_DEPTH_SIZE:
2322     case GraphicsContext3D::RENDERBUFFER_STENCIL_SIZE:
2323         m_context->getRenderbufferParameteriv(target, pname, &value);
2324         return WebGLGetInfo(value);
2325     case GraphicsContext3D::RENDERBUFFER_INTERNAL_FORMAT:
2326         return WebGLGetInfo(m_renderbufferBinding->getInternalFormat());
2327     default:
2328         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
2329         return WebGLGetInfo();
2330     }
2331 }
2332 
getShaderParameter(WebGLShader * shader,GC3Denum pname,ExceptionCode & ec)2333 WebGLGetInfo WebGLRenderingContext::getShaderParameter(WebGLShader* shader, GC3Denum pname, ExceptionCode& ec)
2334 {
2335     UNUSED_PARAM(ec);
2336     if (isContextLost() || !validateWebGLObject(shader))
2337         return WebGLGetInfo();
2338     WebGLStateRestorer(this, false);
2339     GC3Dint value = 0;
2340     switch (pname) {
2341     case GraphicsContext3D::DELETE_STATUS:
2342         return WebGLGetInfo(shader->isDeleted());
2343     case GraphicsContext3D::COMPILE_STATUS:
2344         m_context->getShaderiv(objectOrZero(shader), pname, &value);
2345         return WebGLGetInfo(static_cast<bool>(value));
2346     case GraphicsContext3D::SHADER_TYPE:
2347         m_context->getShaderiv(objectOrZero(shader), pname, &value);
2348         return WebGLGetInfo(static_cast<unsigned int>(value));
2349     default:
2350         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
2351         return WebGLGetInfo();
2352     }
2353 }
2354 
getShaderInfoLog(WebGLShader * shader,ExceptionCode & ec)2355 String WebGLRenderingContext::getShaderInfoLog(WebGLShader* shader, ExceptionCode& ec)
2356 {
2357     UNUSED_PARAM(ec);
2358     if (isContextLost())
2359         return String();
2360     if (!validateWebGLObject(shader))
2361         return "";
2362     WebGLStateRestorer(this, false);
2363     return m_context->getShaderInfoLog(objectOrZero(shader));
2364 }
2365 
getShaderSource(WebGLShader * shader,ExceptionCode & ec)2366 String WebGLRenderingContext::getShaderSource(WebGLShader* shader, ExceptionCode& ec)
2367 {
2368     UNUSED_PARAM(ec);
2369     if (isContextLost())
2370         return String();
2371     if (!validateWebGLObject(shader))
2372         return "";
2373     return shader->getSource();
2374 }
2375 
getSupportedExtensions()2376 Vector<String> WebGLRenderingContext::getSupportedExtensions()
2377 {
2378     Vector<String> result;
2379     if (m_context->getExtensions()->supports("GL_OES_texture_float"))
2380         result.append("OES_texture_float");
2381     if (m_context->getExtensions()->supports("GL_OES_standard_derivatives"))
2382         result.append("OES_standard_derivatives");
2383     if (m_context->getExtensions()->supports("GL_OES_vertex_array_object"))
2384         result.append("OES_vertex_array_object");
2385     result.append("WEBKIT_lose_context");
2386     return result;
2387 }
2388 
getTexParameter(GC3Denum target,GC3Denum pname,ExceptionCode & ec)2389 WebGLGetInfo WebGLRenderingContext::getTexParameter(GC3Denum target, GC3Denum pname, ExceptionCode& ec)
2390 {
2391     UNUSED_PARAM(ec);
2392     if (isContextLost())
2393         return WebGLGetInfo();
2394     WebGLTexture* tex = validateTextureBinding(target, false);
2395     if (!tex)
2396         return WebGLGetInfo();
2397     WebGLStateRestorer(this, false);
2398     GC3Dint value = 0;
2399     switch (pname) {
2400     case GraphicsContext3D::TEXTURE_MAG_FILTER:
2401     case GraphicsContext3D::TEXTURE_MIN_FILTER:
2402     case GraphicsContext3D::TEXTURE_WRAP_S:
2403     case GraphicsContext3D::TEXTURE_WRAP_T:
2404         m_context->getTexParameteriv(target, pname, &value);
2405         return WebGLGetInfo(static_cast<unsigned int>(value));
2406     default:
2407         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
2408         return WebGLGetInfo();
2409     }
2410 }
2411 
getUniform(WebGLProgram * program,const WebGLUniformLocation * uniformLocation,ExceptionCode & ec)2412 WebGLGetInfo WebGLRenderingContext::getUniform(WebGLProgram* program, const WebGLUniformLocation* uniformLocation, ExceptionCode& ec)
2413 {
2414     UNUSED_PARAM(ec);
2415     if (isContextLost() || !validateWebGLObject(program))
2416         return WebGLGetInfo();
2417     if (!uniformLocation || uniformLocation->program() != program) {
2418         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
2419         return WebGLGetInfo();
2420     }
2421     GC3Dint location = uniformLocation->location();
2422 
2423     WebGLStateRestorer(this, false);
2424     // FIXME: make this more efficient using WebGLUniformLocation and caching types in it
2425     GC3Dint activeUniforms = 0;
2426     m_context->getProgramiv(objectOrZero(program), GraphicsContext3D::ACTIVE_UNIFORMS, &activeUniforms);
2427     for (GC3Dint i = 0; i < activeUniforms; i++) {
2428         ActiveInfo info;
2429         if (!m_context->getActiveUniform(objectOrZero(program), i, info))
2430             return WebGLGetInfo();
2431         // Strip "[0]" from the name if it's an array.
2432         if (info.size > 1)
2433             info.name = info.name.left(info.name.length() - 3);
2434         // If it's an array, we need to iterate through each element, appending "[index]" to the name.
2435         for (GC3Dint index = 0; index < info.size; ++index) {
2436             String name = info.name;
2437             if (info.size > 1 && index >= 1) {
2438                 name.append('[');
2439                 name.append(String::number(index));
2440                 name.append(']');
2441             }
2442             // Now need to look this up by name again to find its location
2443             GC3Dint loc = m_context->getUniformLocation(objectOrZero(program), name);
2444             if (loc == location) {
2445                 // Found it. Use the type in the ActiveInfo to determine the return type.
2446                 GC3Denum baseType;
2447                 unsigned int length;
2448                 switch (info.type) {
2449                 case GraphicsContext3D::BOOL:
2450                     baseType = GraphicsContext3D::BOOL;
2451                     length = 1;
2452                     break;
2453                 case GraphicsContext3D::BOOL_VEC2:
2454                     baseType = GraphicsContext3D::BOOL;
2455                     length = 2;
2456                     break;
2457                 case GraphicsContext3D::BOOL_VEC3:
2458                     baseType = GraphicsContext3D::BOOL;
2459                     length = 3;
2460                     break;
2461                 case GraphicsContext3D::BOOL_VEC4:
2462                     baseType = GraphicsContext3D::BOOL;
2463                     length = 4;
2464                     break;
2465                 case GraphicsContext3D::INT:
2466                     baseType = GraphicsContext3D::INT;
2467                     length = 1;
2468                     break;
2469                 case GraphicsContext3D::INT_VEC2:
2470                     baseType = GraphicsContext3D::INT;
2471                     length = 2;
2472                     break;
2473                 case GraphicsContext3D::INT_VEC3:
2474                     baseType = GraphicsContext3D::INT;
2475                     length = 3;
2476                     break;
2477                 case GraphicsContext3D::INT_VEC4:
2478                     baseType = GraphicsContext3D::INT;
2479                     length = 4;
2480                     break;
2481                 case GraphicsContext3D::FLOAT:
2482                     baseType = GraphicsContext3D::FLOAT;
2483                     length = 1;
2484                     break;
2485                 case GraphicsContext3D::FLOAT_VEC2:
2486                     baseType = GraphicsContext3D::FLOAT;
2487                     length = 2;
2488                     break;
2489                 case GraphicsContext3D::FLOAT_VEC3:
2490                     baseType = GraphicsContext3D::FLOAT;
2491                     length = 3;
2492                     break;
2493                 case GraphicsContext3D::FLOAT_VEC4:
2494                     baseType = GraphicsContext3D::FLOAT;
2495                     length = 4;
2496                     break;
2497                 case GraphicsContext3D::FLOAT_MAT2:
2498                     baseType = GraphicsContext3D::FLOAT;
2499                     length = 4;
2500                     break;
2501                 case GraphicsContext3D::FLOAT_MAT3:
2502                     baseType = GraphicsContext3D::FLOAT;
2503                     length = 9;
2504                     break;
2505                 case GraphicsContext3D::FLOAT_MAT4:
2506                     baseType = GraphicsContext3D::FLOAT;
2507                     length = 16;
2508                     break;
2509                 case GraphicsContext3D::SAMPLER_2D:
2510                 case GraphicsContext3D::SAMPLER_CUBE:
2511                     baseType = GraphicsContext3D::INT;
2512                     length = 1;
2513                     break;
2514                 default:
2515                     // Can't handle this type
2516                     m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
2517                     return WebGLGetInfo();
2518                 }
2519                 switch (baseType) {
2520                 case GraphicsContext3D::FLOAT: {
2521                     GC3Dfloat value[16] = {0};
2522                     m_context->getUniformfv(objectOrZero(program), location, value);
2523                     if (length == 1)
2524                         return WebGLGetInfo(value[0]);
2525                     return WebGLGetInfo(Float32Array::create(value, length));
2526                 }
2527                 case GraphicsContext3D::INT: {
2528                     GC3Dint value[4] = {0};
2529                     m_context->getUniformiv(objectOrZero(program), location, value);
2530                     if (length == 1)
2531                         return WebGLGetInfo(value[0]);
2532                     return WebGLGetInfo(Int32Array::create(value, length));
2533                 }
2534                 case GraphicsContext3D::BOOL: {
2535                     GC3Dint value[4] = {0};
2536                     m_context->getUniformiv(objectOrZero(program), location, value);
2537                     if (length > 1) {
2538                         bool boolValue[16] = {0};
2539                         for (unsigned j = 0; j < length; j++)
2540                             boolValue[j] = static_cast<bool>(value[j]);
2541                         return WebGLGetInfo(boolValue, length);
2542                     }
2543                     return WebGLGetInfo(static_cast<bool>(value[0]));
2544                 }
2545                 default:
2546                     notImplemented();
2547                 }
2548             }
2549         }
2550     }
2551     // If we get here, something went wrong in our unfortunately complex logic above
2552     m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
2553     return WebGLGetInfo();
2554 }
2555 
getUniformLocation(WebGLProgram * program,const String & name,ExceptionCode & ec)2556 PassRefPtr<WebGLUniformLocation> WebGLRenderingContext::getUniformLocation(WebGLProgram* program, const String& name, ExceptionCode& ec)
2557 {
2558     UNUSED_PARAM(ec);
2559     if (isContextLost() || !validateWebGLObject(program))
2560         return 0;
2561     if (!validateString(name))
2562         return 0;
2563     WebGLStateRestorer(this, false);
2564     GC3Dint uniformLocation = m_context->getUniformLocation(objectOrZero(program), name);
2565     if (uniformLocation == -1)
2566         return 0;
2567     return WebGLUniformLocation::create(program, uniformLocation);
2568 }
2569 
getVertexAttrib(GC3Duint index,GC3Denum pname,ExceptionCode & ec)2570 WebGLGetInfo WebGLRenderingContext::getVertexAttrib(GC3Duint index, GC3Denum pname, ExceptionCode& ec)
2571 {
2572     UNUSED_PARAM(ec);
2573     if (isContextLost())
2574         return WebGLGetInfo();
2575     WebGLStateRestorer(this, false);
2576     if (index >= m_maxVertexAttribs) {
2577         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
2578         return WebGLGetInfo();
2579     }
2580     const WebGLVertexArrayObjectOES::VertexAttribState& state = m_boundVertexArrayObject->getVertexAttribState(index);
2581     switch (pname) {
2582     case GraphicsContext3D::VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
2583         if ((!isGLES2Compliant() && !index && m_boundVertexArrayObject->getVertexAttribState(0).bufferBinding == m_vertexAttrib0Buffer)
2584             || !state.bufferBinding
2585             || !state.bufferBinding->object())
2586             return WebGLGetInfo();
2587         return WebGLGetInfo(PassRefPtr<WebGLBuffer>(state.bufferBinding));
2588     case GraphicsContext3D::VERTEX_ATTRIB_ARRAY_ENABLED:
2589         return WebGLGetInfo(state.enabled);
2590     case GraphicsContext3D::VERTEX_ATTRIB_ARRAY_NORMALIZED:
2591         return WebGLGetInfo(state.normalized);
2592     case GraphicsContext3D::VERTEX_ATTRIB_ARRAY_SIZE:
2593         return WebGLGetInfo(state.size);
2594     case GraphicsContext3D::VERTEX_ATTRIB_ARRAY_STRIDE:
2595         return WebGLGetInfo(state.originalStride);
2596     case GraphicsContext3D::VERTEX_ATTRIB_ARRAY_TYPE:
2597         return WebGLGetInfo(state.type);
2598     case GraphicsContext3D::CURRENT_VERTEX_ATTRIB:
2599         return WebGLGetInfo(Float32Array::create(m_vertexAttribValue[index].value, 4));
2600     default:
2601         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
2602         return WebGLGetInfo();
2603     }
2604 }
2605 
getVertexAttribOffset(GC3Duint index,GC3Denum pname)2606 GC3Dsizeiptr WebGLRenderingContext::getVertexAttribOffset(GC3Duint index, GC3Denum pname)
2607 {
2608     if (isContextLost())
2609         return 0;
2610     GC3Dsizeiptr result = m_context->getVertexAttribOffset(index, pname);
2611     cleanupAfterGraphicsCall(false);
2612     return result;
2613 }
2614 
hint(GC3Denum target,GC3Denum mode)2615 void WebGLRenderingContext::hint(GC3Denum target, GC3Denum mode)
2616 {
2617     if (isContextLost())
2618         return;
2619     bool isValid = false;
2620     switch (target) {
2621     case GraphicsContext3D::GENERATE_MIPMAP_HINT:
2622         isValid = true;
2623         break;
2624     case Extensions3D::FRAGMENT_SHADER_DERIVATIVE_HINT_OES: // OES_standard_derivatives
2625         if (m_oesStandardDerivatives)
2626             isValid = true;
2627         break;
2628     }
2629     if (!isValid) {
2630         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
2631         return;
2632     }
2633     m_context->hint(target, mode);
2634     cleanupAfterGraphicsCall(false);
2635 }
2636 
isBuffer(WebGLBuffer * buffer)2637 GC3Dboolean WebGLRenderingContext::isBuffer(WebGLBuffer* buffer)
2638 {
2639     if (!buffer || isContextLost())
2640         return 0;
2641 
2642     if (!buffer->hasEverBeenBound())
2643         return 0;
2644 
2645     return m_context->isBuffer(buffer->object());
2646 }
2647 
isContextLost()2648 bool WebGLRenderingContext::isContextLost()
2649 {
2650     if (m_restoreTimer.isActive())
2651         return true;
2652 
2653     bool newContextLost = m_context->getExtensions()->getGraphicsResetStatusARB() != GraphicsContext3D::NO_ERROR;
2654 
2655     if (newContextLost != m_contextLost)
2656         m_restoreTimer.startOneShot(secondsBetweenRestoreAttempts);
2657 
2658     return m_contextLost;
2659 }
2660 
isEnabled(GC3Denum cap)2661 GC3Dboolean WebGLRenderingContext::isEnabled(GC3Denum cap)
2662 {
2663     if (!validateCapability(cap) || isContextLost())
2664         return 0;
2665     return m_context->isEnabled(cap);
2666 }
2667 
isFramebuffer(WebGLFramebuffer * framebuffer)2668 GC3Dboolean WebGLRenderingContext::isFramebuffer(WebGLFramebuffer* framebuffer)
2669 {
2670     if (!framebuffer || isContextLost())
2671         return 0;
2672 
2673     if (!framebuffer->hasEverBeenBound())
2674         return 0;
2675 
2676     return m_context->isFramebuffer(framebuffer->object());
2677 }
2678 
isProgram(WebGLProgram * program)2679 GC3Dboolean WebGLRenderingContext::isProgram(WebGLProgram* program)
2680 {
2681     if (!program || isContextLost())
2682         return 0;
2683 
2684     return m_context->isProgram(program->object());
2685 }
2686 
isRenderbuffer(WebGLRenderbuffer * renderbuffer)2687 GC3Dboolean WebGLRenderingContext::isRenderbuffer(WebGLRenderbuffer* renderbuffer)
2688 {
2689     if (!renderbuffer || isContextLost())
2690         return 0;
2691 
2692     if (!renderbuffer->hasEverBeenBound())
2693         return 0;
2694 
2695     return m_context->isRenderbuffer(renderbuffer->object());
2696 }
2697 
isShader(WebGLShader * shader)2698 GC3Dboolean WebGLRenderingContext::isShader(WebGLShader* shader)
2699 {
2700     if (!shader || isContextLost())
2701         return 0;
2702 
2703     return m_context->isShader(shader->object());
2704 }
2705 
isTexture(WebGLTexture * texture)2706 GC3Dboolean WebGLRenderingContext::isTexture(WebGLTexture* texture)
2707 {
2708     if (!texture || isContextLost())
2709         return 0;
2710 
2711     if (!texture->hasEverBeenBound())
2712         return 0;
2713 
2714     return m_context->isTexture(texture->object());
2715 }
2716 
lineWidth(GC3Dfloat width)2717 void WebGLRenderingContext::lineWidth(GC3Dfloat width)
2718 {
2719     if (isContextLost())
2720         return;
2721     m_context->lineWidth(width);
2722     cleanupAfterGraphicsCall(false);
2723 }
2724 
linkProgram(WebGLProgram * program,ExceptionCode & ec)2725 void WebGLRenderingContext::linkProgram(WebGLProgram* program, ExceptionCode& ec)
2726 {
2727     UNUSED_PARAM(ec);
2728     if (isContextLost() || !validateWebGLObject(program))
2729         return;
2730     if (!isGLES2Compliant()) {
2731         if (!program->getAttachedShader(GraphicsContext3D::VERTEX_SHADER) || !program->getAttachedShader(GraphicsContext3D::FRAGMENT_SHADER)) {
2732             program->setLinkStatus(false);
2733             return;
2734         }
2735     }
2736 
2737     m_context->linkProgram(objectOrZero(program));
2738     program->increaseLinkCount();
2739     // cache link status
2740     GC3Dint value = 0;
2741     m_context->getProgramiv(objectOrZero(program), GraphicsContext3D::LINK_STATUS, &value);
2742     program->setLinkStatus(static_cast<bool>(value));
2743     // Need to cache link status before caching active attribute locations.
2744     program->cacheActiveAttribLocations();
2745     cleanupAfterGraphicsCall(false);
2746 }
2747 
pixelStorei(GC3Denum pname,GC3Dint param)2748 void WebGLRenderingContext::pixelStorei(GC3Denum pname, GC3Dint param)
2749 {
2750     if (isContextLost())
2751         return;
2752     switch (pname) {
2753     case GraphicsContext3D::UNPACK_FLIP_Y_WEBGL:
2754         m_unpackFlipY = param;
2755         break;
2756     case GraphicsContext3D::UNPACK_PREMULTIPLY_ALPHA_WEBGL:
2757         m_unpackPremultiplyAlpha = param;
2758         break;
2759     case GraphicsContext3D::UNPACK_COLORSPACE_CONVERSION_WEBGL:
2760         if (param == GraphicsContext3D::BROWSER_DEFAULT_WEBGL || param == GraphicsContext3D::NONE)
2761             m_unpackColorspaceConversion = static_cast<GC3Denum>(param);
2762         else {
2763             m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
2764             return;
2765         }
2766         break;
2767     case GraphicsContext3D::PACK_ALIGNMENT:
2768     case GraphicsContext3D::UNPACK_ALIGNMENT:
2769         if (param == 1 || param == 2 || param == 4 || param == 8) {
2770             if (pname == GraphicsContext3D::PACK_ALIGNMENT)
2771                 m_packAlignment = param;
2772             else // GraphicsContext3D::UNPACK_ALIGNMENT:
2773                 m_unpackAlignment = param;
2774             m_context->pixelStorei(pname, param);
2775             cleanupAfterGraphicsCall(false);
2776         } else {
2777             m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
2778             return;
2779         }
2780         break;
2781     default:
2782         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
2783         return;
2784     }
2785 }
2786 
polygonOffset(GC3Dfloat factor,GC3Dfloat units)2787 void WebGLRenderingContext::polygonOffset(GC3Dfloat factor, GC3Dfloat units)
2788 {
2789     if (isContextLost())
2790         return;
2791     m_context->polygonOffset(factor, units);
2792     cleanupAfterGraphicsCall(false);
2793 }
2794 
readPixels(GC3Dint x,GC3Dint y,GC3Dsizei width,GC3Dsizei height,GC3Denum format,GC3Denum type,ArrayBufferView * pixels,ExceptionCode & ec)2795 void WebGLRenderingContext::readPixels(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height, GC3Denum format, GC3Denum type, ArrayBufferView* pixels, ExceptionCode& ec)
2796 {
2797     if (isContextLost())
2798         return;
2799     if (!canvas()->originClean()) {
2800         ec = SECURITY_ERR;
2801         return;
2802     }
2803     // Validate input parameters.
2804     if (!pixels) {
2805         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
2806         return;
2807     }
2808     switch (format) {
2809     case GraphicsContext3D::ALPHA:
2810     case GraphicsContext3D::RGB:
2811     case GraphicsContext3D::RGBA:
2812         break;
2813     default:
2814         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
2815         return;
2816     }
2817     switch (type) {
2818     case GraphicsContext3D::UNSIGNED_BYTE:
2819     case GraphicsContext3D::UNSIGNED_SHORT_5_6_5:
2820     case GraphicsContext3D::UNSIGNED_SHORT_4_4_4_4:
2821     case GraphicsContext3D::UNSIGNED_SHORT_5_5_5_1:
2822         break;
2823     default:
2824         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
2825         return;
2826     }
2827     if (format != GraphicsContext3D::RGBA || type != GraphicsContext3D::UNSIGNED_BYTE) {
2828         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
2829         return;
2830     }
2831     // Validate array type against pixel type.
2832     if (!pixels->isUnsignedByteArray()) {
2833         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
2834         return;
2835     }
2836     if (m_framebufferBinding && !m_framebufferBinding->onAccess(!isResourceSafe())) {
2837         m_context->synthesizeGLError(GraphicsContext3D::INVALID_FRAMEBUFFER_OPERATION);
2838         return;
2839     }
2840     // Calculate array size, taking into consideration of PACK_ALIGNMENT.
2841     unsigned int totalBytesRequired;
2842     unsigned int padding;
2843     GC3Denum error = m_context->computeImageSizeInBytes(format, type, width, height, m_packAlignment, &totalBytesRequired, &padding);
2844     if (error != GraphicsContext3D::NO_ERROR) {
2845         m_context->synthesizeGLError(error);
2846         return;
2847     }
2848     if (pixels->byteLength() < totalBytesRequired) {
2849         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
2850         return;
2851     }
2852     clearIfComposited();
2853     void* data = pixels->baseAddress();
2854     m_context->readPixels(x, y, width, height, format, type, data);
2855 #if OS(DARWIN)
2856     // FIXME: remove this section when GL driver bug on Mac is fixed, i.e.,
2857     // when alpha is off, readPixels should set alpha to 255 instead of 0.
2858     if (!m_context->getContextAttributes().alpha) {
2859         unsigned char* pixels = reinterpret_cast<unsigned char*>(data);
2860         for (GC3Dsizei iy = 0; iy < height; ++iy) {
2861             for (GC3Dsizei ix = 0; ix < width; ++ix) {
2862                 pixels[3] = 255;
2863                 pixels += 4;
2864             }
2865             pixels += padding;
2866         }
2867     }
2868 #endif
2869     cleanupAfterGraphicsCall(false);
2870 }
2871 
releaseShaderCompiler()2872 void WebGLRenderingContext::releaseShaderCompiler()
2873 {
2874     if (isContextLost())
2875         return;
2876     m_context->releaseShaderCompiler();
2877     cleanupAfterGraphicsCall(false);
2878 }
2879 
renderbufferStorage(GC3Denum target,GC3Denum internalformat,GC3Dsizei width,GC3Dsizei height)2880 void WebGLRenderingContext::renderbufferStorage(GC3Denum target, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height)
2881 {
2882     if (isContextLost())
2883         return;
2884     if (target != GraphicsContext3D::RENDERBUFFER) {
2885         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
2886         return;
2887     }
2888     if (!m_renderbufferBinding || !m_renderbufferBinding->object()) {
2889         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
2890         return;
2891     }
2892     if (!validateSize(width, height))
2893         return;
2894     switch (internalformat) {
2895     case GraphicsContext3D::DEPTH_COMPONENT16:
2896     case GraphicsContext3D::RGBA4:
2897     case GraphicsContext3D::RGB5_A1:
2898     case GraphicsContext3D::RGB565:
2899     case GraphicsContext3D::STENCIL_INDEX8:
2900         m_context->renderbufferStorage(target, internalformat, width, height);
2901         m_renderbufferBinding->setInternalFormat(internalformat);
2902         m_renderbufferBinding->setIsValid(true);
2903         m_renderbufferBinding->setSize(width, height);
2904         cleanupAfterGraphicsCall(false);
2905         break;
2906     case GraphicsContext3D::DEPTH_STENCIL:
2907         if (isDepthStencilSupported()) {
2908             m_context->renderbufferStorage(target, Extensions3D::DEPTH24_STENCIL8, width, height);
2909             cleanupAfterGraphicsCall(false);
2910         }
2911         m_renderbufferBinding->setSize(width, height);
2912         m_renderbufferBinding->setIsValid(isDepthStencilSupported());
2913         m_renderbufferBinding->setInternalFormat(internalformat);
2914         break;
2915     default:
2916         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
2917     }
2918 }
2919 
sampleCoverage(GC3Dfloat value,GC3Dboolean invert)2920 void WebGLRenderingContext::sampleCoverage(GC3Dfloat value, GC3Dboolean invert)
2921 {
2922     if (isContextLost())
2923         return;
2924     m_context->sampleCoverage(value, invert);
2925     cleanupAfterGraphicsCall(false);
2926 }
2927 
scissor(GC3Dint x,GC3Dint y,GC3Dsizei width,GC3Dsizei height)2928 void WebGLRenderingContext::scissor(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height)
2929 {
2930     if (isContextLost())
2931         return;
2932     if (!validateSize(width, height))
2933         return;
2934     m_context->scissor(x, y, width, height);
2935     cleanupAfterGraphicsCall(false);
2936 }
2937 
shaderSource(WebGLShader * shader,const String & string,ExceptionCode & ec)2938 void WebGLRenderingContext::shaderSource(WebGLShader* shader, const String& string, ExceptionCode& ec)
2939 {
2940     UNUSED_PARAM(ec);
2941     if (isContextLost() || !validateWebGLObject(shader))
2942         return;
2943     String stringWithoutComments = StripComments(string).result();
2944     if (!validateString(stringWithoutComments))
2945         return;
2946     shader->setSource(string);
2947     m_context->shaderSource(objectOrZero(shader), stringWithoutComments);
2948     cleanupAfterGraphicsCall(false);
2949 }
2950 
stencilFunc(GC3Denum func,GC3Dint ref,GC3Duint mask)2951 void WebGLRenderingContext::stencilFunc(GC3Denum func, GC3Dint ref, GC3Duint mask)
2952 {
2953     if (isContextLost())
2954         return;
2955     if (!validateStencilFunc(func))
2956         return;
2957     m_stencilFuncRef = ref;
2958     m_stencilFuncRefBack = ref;
2959     m_stencilFuncMask = mask;
2960     m_stencilFuncMaskBack = mask;
2961     m_context->stencilFunc(func, ref, mask);
2962     cleanupAfterGraphicsCall(false);
2963 }
2964 
stencilFuncSeparate(GC3Denum face,GC3Denum func,GC3Dint ref,GC3Duint mask)2965 void WebGLRenderingContext::stencilFuncSeparate(GC3Denum face, GC3Denum func, GC3Dint ref, GC3Duint mask)
2966 {
2967     if (isContextLost())
2968         return;
2969     if (!validateStencilFunc(func))
2970         return;
2971     switch (face) {
2972     case GraphicsContext3D::FRONT_AND_BACK:
2973         m_stencilFuncRef = ref;
2974         m_stencilFuncRefBack = ref;
2975         m_stencilFuncMask = mask;
2976         m_stencilFuncMaskBack = mask;
2977         break;
2978     case GraphicsContext3D::FRONT:
2979         m_stencilFuncRef = ref;
2980         m_stencilFuncMask = mask;
2981         break;
2982     case GraphicsContext3D::BACK:
2983         m_stencilFuncRefBack = ref;
2984         m_stencilFuncMaskBack = mask;
2985         break;
2986     default:
2987         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
2988         return;
2989     }
2990     m_context->stencilFuncSeparate(face, func, ref, mask);
2991     cleanupAfterGraphicsCall(false);
2992 }
2993 
stencilMask(GC3Duint mask)2994 void WebGLRenderingContext::stencilMask(GC3Duint mask)
2995 {
2996     if (isContextLost())
2997         return;
2998     m_stencilMask = mask;
2999     m_stencilMaskBack = mask;
3000     m_context->stencilMask(mask);
3001     cleanupAfterGraphicsCall(false);
3002 }
3003 
stencilMaskSeparate(GC3Denum face,GC3Duint mask)3004 void WebGLRenderingContext::stencilMaskSeparate(GC3Denum face, GC3Duint mask)
3005 {
3006     if (isContextLost())
3007         return;
3008     switch (face) {
3009     case GraphicsContext3D::FRONT_AND_BACK:
3010         m_stencilMask = mask;
3011         m_stencilMaskBack = mask;
3012         break;
3013     case GraphicsContext3D::FRONT:
3014         m_stencilMask = mask;
3015         break;
3016     case GraphicsContext3D::BACK:
3017         m_stencilMaskBack = mask;
3018         break;
3019     default:
3020         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
3021         return;
3022     }
3023     m_context->stencilMaskSeparate(face, mask);
3024     cleanupAfterGraphicsCall(false);
3025 }
3026 
stencilOp(GC3Denum fail,GC3Denum zfail,GC3Denum zpass)3027 void WebGLRenderingContext::stencilOp(GC3Denum fail, GC3Denum zfail, GC3Denum zpass)
3028 {
3029     if (isContextLost())
3030         return;
3031     m_context->stencilOp(fail, zfail, zpass);
3032     cleanupAfterGraphicsCall(false);
3033 }
3034 
stencilOpSeparate(GC3Denum face,GC3Denum fail,GC3Denum zfail,GC3Denum zpass)3035 void WebGLRenderingContext::stencilOpSeparate(GC3Denum face, GC3Denum fail, GC3Denum zfail, GC3Denum zpass)
3036 {
3037     if (isContextLost())
3038         return;
3039     m_context->stencilOpSeparate(face, fail, zfail, zpass);
3040     cleanupAfterGraphicsCall(false);
3041 }
3042 
texImage2DBase(GC3Denum target,GC3Dint level,GC3Denum internalformat,GC3Dsizei width,GC3Dsizei height,GC3Dint border,GC3Denum format,GC3Denum type,void * pixels,ExceptionCode & ec)3043 void WebGLRenderingContext::texImage2DBase(GC3Denum target, GC3Dint level, GC3Denum internalformat,
3044                                            GC3Dsizei width, GC3Dsizei height, GC3Dint border,
3045                                            GC3Denum format, GC3Denum type, void* pixels, ExceptionCode& ec)
3046 {
3047     // FIXME: For now we ignore any errors returned
3048     ec = 0;
3049     if (!validateTexFuncParameters(target, level, internalformat, width, height, border, format, type))
3050         return;
3051     WebGLTexture* tex = validateTextureBinding(target, true);
3052     if (!tex)
3053         return;
3054     if (!isGLES2NPOTStrict()) {
3055         if (level && WebGLTexture::isNPOT(width, height)) {
3056             m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
3057             return;
3058         }
3059     }
3060     if (!pixels && !isResourceSafe()) {
3061         bool succeed = m_context->texImage2DResourceSafe(target, level, internalformat, width, height,
3062                                                          border, format, type, m_unpackAlignment);
3063         if (!succeed)
3064             return;
3065     } else {
3066         m_context->texImage2D(target, level, internalformat, width, height,
3067                               border, format, type, pixels);
3068     }
3069     tex->setLevelInfo(target, level, internalformat, width, height, type);
3070     cleanupAfterGraphicsCall(false);
3071 }
3072 
texImage2DImpl(GC3Denum target,GC3Dint level,GC3Denum internalformat,GC3Denum format,GC3Denum type,Image * image,bool flipY,bool premultiplyAlpha,ExceptionCode & ec)3073 void WebGLRenderingContext::texImage2DImpl(GC3Denum target, GC3Dint level, GC3Denum internalformat,
3074                                            GC3Denum format, GC3Denum type, Image* image,
3075                                            bool flipY, bool premultiplyAlpha, ExceptionCode& ec)
3076 {
3077     ec = 0;
3078     Vector<uint8_t> data;
3079     if (!m_context->extractImageData(image, format, type, flipY, premultiplyAlpha, m_unpackColorspaceConversion == GraphicsContext3D::NONE, data)) {
3080         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
3081         return;
3082     }
3083     if (m_unpackAlignment != 1)
3084         m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, 1);
3085     texImage2DBase(target, level, internalformat, image->width(), image->height(), 0,
3086                    format, type, data.data(), ec);
3087     if (m_unpackAlignment != 1)
3088         m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, m_unpackAlignment);
3089 }
3090 
texImage2D(GC3Denum target,GC3Dint level,GC3Denum internalformat,GC3Dsizei width,GC3Dsizei height,GC3Dint border,GC3Denum format,GC3Denum type,ArrayBufferView * pixels,ExceptionCode & ec)3091 void WebGLRenderingContext::texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat,
3092                                        GC3Dsizei width, GC3Dsizei height, GC3Dint border,
3093                                        GC3Denum format, GC3Denum type, ArrayBufferView* pixels, ExceptionCode& ec)
3094 {
3095     if (isContextLost() || !validateTexFuncData(width, height, format, type, pixels))
3096         return;
3097     void* data = pixels ? pixels->baseAddress() : 0;
3098     Vector<uint8_t> tempData;
3099     bool changeUnpackAlignment = false;
3100     if (data && (m_unpackFlipY || m_unpackPremultiplyAlpha)) {
3101         if (!m_context->extractTextureData(width, height, format, type,
3102                                            m_unpackAlignment,
3103                                            m_unpackFlipY, m_unpackPremultiplyAlpha,
3104                                            data,
3105                                            tempData))
3106             return;
3107         data = tempData.data();
3108         changeUnpackAlignment = true;
3109     }
3110     if (changeUnpackAlignment)
3111         m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, 1);
3112     texImage2DBase(target, level, internalformat, width, height, border,
3113                    format, type, data, ec);
3114     if (changeUnpackAlignment)
3115         m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, m_unpackAlignment);
3116 }
3117 
texImage2D(GC3Denum target,GC3Dint level,GC3Denum internalformat,GC3Denum format,GC3Denum type,ImageData * pixels,ExceptionCode & ec)3118 void WebGLRenderingContext::texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat,
3119                                        GC3Denum format, GC3Denum type, ImageData* pixels, ExceptionCode& ec)
3120 {
3121     ec = 0;
3122     if (isContextLost())
3123         return;
3124     Vector<uint8_t> data;
3125     if (!m_context->extractImageData(pixels, format, type, m_unpackFlipY, m_unpackPremultiplyAlpha, data)) {
3126         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
3127         return;
3128     }
3129     if (m_unpackAlignment != 1)
3130         m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, 1);
3131     texImage2DBase(target, level, internalformat, pixels->width(), pixels->height(), 0,
3132                    format, type, data.data(), ec);
3133     if (m_unpackAlignment != 1)
3134         m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, m_unpackAlignment);
3135 }
3136 
texImage2D(GC3Denum target,GC3Dint level,GC3Denum internalformat,GC3Denum format,GC3Denum type,HTMLImageElement * image,ExceptionCode & ec)3137 void WebGLRenderingContext::texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat,
3138                                        GC3Denum format, GC3Denum type, HTMLImageElement* image, ExceptionCode& ec)
3139 {
3140     ec = 0;
3141     if (isContextLost())
3142         return;
3143     if (!validateHTMLImageElement(image))
3144         return;
3145     checkOrigin(image);
3146     texImage2DImpl(target, level, internalformat, format, type, image->cachedImage()->image(),
3147                    m_unpackFlipY, m_unpackPremultiplyAlpha, ec);
3148 }
3149 
texImage2D(GC3Denum target,GC3Dint level,GC3Denum internalformat,GC3Denum format,GC3Denum type,HTMLCanvasElement * canvas,ExceptionCode & ec)3150 void WebGLRenderingContext::texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat,
3151                                        GC3Denum format, GC3Denum type, HTMLCanvasElement* canvas, ExceptionCode& ec)
3152 {
3153     ec = 0;
3154     if (isContextLost())
3155         return;
3156     if (!canvas || !canvas->buffer()) {
3157         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
3158         return;
3159     }
3160     checkOrigin(canvas);
3161     RefPtr<ImageData> imageData = canvas->getImageData();
3162     if (imageData)
3163         texImage2D(target, level, internalformat, format, type, imageData.get(), ec);
3164     else
3165         texImage2DImpl(target, level, internalformat, format, type, canvas->copiedImage(),
3166                        m_unpackFlipY, m_unpackPremultiplyAlpha, ec);
3167 }
3168 
3169 #if ENABLE(VIDEO)
videoFrameToImage(HTMLVideoElement * video)3170 PassRefPtr<Image> WebGLRenderingContext::videoFrameToImage(HTMLVideoElement* video)
3171 {
3172     if (!video || !video->videoWidth() || !video->videoHeight()) {
3173         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
3174         return 0;
3175     }
3176     IntSize size(video->videoWidth(), video->videoHeight());
3177     ImageBuffer* buf = m_videoCache.imageBuffer(size);
3178     if (!buf) {
3179         m_context->synthesizeGLError(GraphicsContext3D::OUT_OF_MEMORY);
3180         return 0;
3181     }
3182     checkOrigin(video);
3183     IntRect destRect(0, 0, size.width(), size.height());
3184     // FIXME: Turn this into a GPU-GPU texture copy instead of CPU readback.
3185     video->paintCurrentFrameInContext(buf->context(), destRect);
3186     return buf->copyImage();
3187 }
3188 
texImage2D(GC3Denum target,GC3Dint level,GC3Denum internalformat,GC3Denum format,GC3Denum type,HTMLVideoElement * video,ExceptionCode & ec)3189 void WebGLRenderingContext::texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat,
3190                                        GC3Denum format, GC3Denum type, HTMLVideoElement* video, ExceptionCode& ec)
3191 {
3192     ec = 0;
3193     if (isContextLost())
3194         return;
3195     RefPtr<Image> image = videoFrameToImage(video);
3196     if (!video)
3197         return;
3198     texImage2DImpl(target, level, internalformat, format, type, image.get(), m_unpackFlipY, m_unpackPremultiplyAlpha, ec);
3199 }
3200 #endif
3201 
texParameter(GC3Denum target,GC3Denum pname,GC3Dfloat paramf,GC3Dint parami,bool isFloat)3202 void WebGLRenderingContext::texParameter(GC3Denum target, GC3Denum pname, GC3Dfloat paramf, GC3Dint parami, bool isFloat)
3203 {
3204     if (isContextLost())
3205         return;
3206     WebGLTexture* tex = validateTextureBinding(target, false);
3207     if (!tex)
3208         return;
3209     switch (pname) {
3210     case GraphicsContext3D::TEXTURE_MIN_FILTER:
3211     case GraphicsContext3D::TEXTURE_MAG_FILTER:
3212         break;
3213     case GraphicsContext3D::TEXTURE_WRAP_S:
3214     case GraphicsContext3D::TEXTURE_WRAP_T:
3215         if ((isFloat && paramf != GraphicsContext3D::CLAMP_TO_EDGE && paramf != GraphicsContext3D::MIRRORED_REPEAT && paramf != GraphicsContext3D::REPEAT)
3216             || (!isFloat && parami != GraphicsContext3D::CLAMP_TO_EDGE && parami != GraphicsContext3D::MIRRORED_REPEAT && parami != GraphicsContext3D::REPEAT)) {
3217             m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
3218             return;
3219         }
3220         break;
3221     default:
3222         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
3223         return;
3224     }
3225     if (isFloat) {
3226         tex->setParameterf(pname, paramf);
3227         m_context->texParameterf(target, pname, paramf);
3228     } else {
3229         tex->setParameteri(pname, parami);
3230         m_context->texParameteri(target, pname, parami);
3231     }
3232     cleanupAfterGraphicsCall(false);
3233 }
3234 
texParameterf(GC3Denum target,GC3Denum pname,GC3Dfloat param)3235 void WebGLRenderingContext::texParameterf(GC3Denum target, GC3Denum pname, GC3Dfloat param)
3236 {
3237     texParameter(target, pname, param, 0, true);
3238 }
3239 
texParameteri(GC3Denum target,GC3Denum pname,GC3Dint param)3240 void WebGLRenderingContext::texParameteri(GC3Denum target, GC3Denum pname, GC3Dint param)
3241 {
3242     texParameter(target, pname, 0, param, false);
3243 }
3244 
texSubImage2DBase(GC3Denum target,GC3Dint level,GC3Dint xoffset,GC3Dint yoffset,GC3Dsizei width,GC3Dsizei height,GC3Denum format,GC3Denum type,void * pixels,ExceptionCode & ec)3245 void WebGLRenderingContext::texSubImage2DBase(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
3246                                               GC3Dsizei width, GC3Dsizei height,
3247                                               GC3Denum format, GC3Denum type, void* pixels, ExceptionCode& ec)
3248 {
3249     // FIXME: For now we ignore any errors returned
3250     ec = 0;
3251     if (isContextLost())
3252         return;
3253     if (!validateTexFuncParameters(target, level, format, width, height, 0, format, type))
3254         return;
3255     if (!validateSize(xoffset, yoffset))
3256         return;
3257     WebGLTexture* tex = validateTextureBinding(target, true);
3258     if (!tex)
3259         return;
3260     if (xoffset + width > tex->getWidth(target, level) || yoffset + height > tex->getHeight(target, level)) {
3261         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
3262         return;
3263     }
3264     if (tex->getInternalFormat(target, level) != format || tex->getType(target, level) != type) {
3265         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
3266         return;
3267     }
3268     m_context->texSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels);
3269     cleanupAfterGraphicsCall(false);
3270 }
3271 
texSubImage2DImpl(GC3Denum target,GC3Dint level,GC3Dint xoffset,GC3Dint yoffset,GC3Denum format,GC3Denum type,Image * image,bool flipY,bool premultiplyAlpha,ExceptionCode & ec)3272 void WebGLRenderingContext::texSubImage2DImpl(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
3273                                               GC3Denum format, GC3Denum type,
3274                                               Image* image, bool flipY, bool premultiplyAlpha, ExceptionCode& ec)
3275 {
3276     ec = 0;
3277     if (isContextLost())
3278         return;
3279     Vector<uint8_t> data;
3280     if (!m_context->extractImageData(image, format, type, flipY, premultiplyAlpha, m_unpackColorspaceConversion == GraphicsContext3D::NONE, data)) {
3281         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
3282         return;
3283     }
3284     texSubImage2DBase(target, level, xoffset, yoffset, image->width(), image->height(),
3285                       format, type, data.data(), ec);
3286 }
3287 
texSubImage2D(GC3Denum target,GC3Dint level,GC3Dint xoffset,GC3Dint yoffset,GC3Dsizei width,GC3Dsizei height,GC3Denum format,GC3Denum type,ArrayBufferView * pixels,ExceptionCode & ec)3288 void WebGLRenderingContext::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
3289                                           GC3Dsizei width, GC3Dsizei height,
3290                                           GC3Denum format, GC3Denum type, ArrayBufferView* pixels, ExceptionCode& ec)
3291 {
3292     if (isContextLost() || !validateTexFuncData(width, height, format, type, pixels))
3293         return;
3294     void* data = pixels ? pixels->baseAddress() : 0;
3295     Vector<uint8_t> tempData;
3296     bool changeUnpackAlignment = false;
3297     if (data && (m_unpackFlipY || m_unpackPremultiplyAlpha)) {
3298         if (!m_context->extractTextureData(width, height, format, type,
3299                                            m_unpackAlignment,
3300                                            m_unpackFlipY, m_unpackPremultiplyAlpha,
3301                                            data,
3302                                            tempData))
3303             return;
3304         data = tempData.data();
3305         changeUnpackAlignment = true;
3306     }
3307     if (changeUnpackAlignment)
3308         m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, 1);
3309     texSubImage2DBase(target, level, xoffset, yoffset, width, height, format, type, data, ec);
3310     if (changeUnpackAlignment)
3311         m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, m_unpackAlignment);
3312 }
3313 
texSubImage2D(GC3Denum target,GC3Dint level,GC3Dint xoffset,GC3Dint yoffset,GC3Denum format,GC3Denum type,ImageData * pixels,ExceptionCode & ec)3314 void WebGLRenderingContext::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
3315                                           GC3Denum format, GC3Denum type, ImageData* pixels, ExceptionCode& ec)
3316 {
3317     ec = 0;
3318     if (isContextLost())
3319         return;
3320     Vector<uint8_t> data;
3321     if (!m_context->extractImageData(pixels, format, type, m_unpackFlipY, m_unpackPremultiplyAlpha, data)) {
3322         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
3323         return;
3324     }
3325     texSubImage2DBase(target, level, xoffset, yoffset, pixels->width(), pixels->height(),
3326                       format, type, data.data(), ec);
3327 }
3328 
texSubImage2D(GC3Denum target,GC3Dint level,GC3Dint xoffset,GC3Dint yoffset,GC3Denum format,GC3Denum type,HTMLImageElement * image,ExceptionCode & ec)3329 void WebGLRenderingContext::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
3330                                           GC3Denum format, GC3Denum type, HTMLImageElement* image, ExceptionCode& ec)
3331 {
3332     ec = 0;
3333     if (isContextLost())
3334         return;
3335     if (!validateHTMLImageElement(image))
3336         return;
3337     checkOrigin(image);
3338     texSubImage2DImpl(target, level, xoffset, yoffset, format, type, image->cachedImage()->image(),
3339                       m_unpackFlipY, m_unpackPremultiplyAlpha, ec);
3340 }
3341 
texSubImage2D(GC3Denum target,GC3Dint level,GC3Dint xoffset,GC3Dint yoffset,GC3Denum format,GC3Denum type,HTMLCanvasElement * canvas,ExceptionCode & ec)3342 void WebGLRenderingContext::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
3343                                           GC3Denum format, GC3Denum type, HTMLCanvasElement* canvas, ExceptionCode& ec)
3344 {
3345     ec = 0;
3346     if (isContextLost())
3347         return;
3348     if (!canvas || !canvas->buffer()) {
3349         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
3350         return;
3351     }
3352     checkOrigin(canvas);
3353     RefPtr<ImageData> imageData = canvas->getImageData();
3354     if (imageData)
3355         texSubImage2D(target, level, xoffset, yoffset, format, type, imageData.get(), ec);
3356     else
3357         texSubImage2DImpl(target, level, xoffset, yoffset, format, type, canvas->copiedImage(),
3358                           m_unpackFlipY, m_unpackPremultiplyAlpha, ec);
3359 }
3360 
3361 #if ENABLE(VIDEO)
texSubImage2D(GC3Denum target,GC3Dint level,GC3Dint xoffset,GC3Dint yoffset,GC3Denum format,GC3Denum type,HTMLVideoElement * video,ExceptionCode & ec)3362 void WebGLRenderingContext::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
3363                                           GC3Denum format, GC3Denum type, HTMLVideoElement* video, ExceptionCode& ec)
3364 {
3365     ec = 0;
3366     if (isContextLost())
3367         return;
3368     RefPtr<Image> image = videoFrameToImage(video);
3369     if (!video)
3370         return;
3371     texSubImage2DImpl(target, level, xoffset, yoffset, format, type, image.get(), m_unpackFlipY, m_unpackPremultiplyAlpha, ec);
3372 }
3373 #endif
3374 
uniform1f(const WebGLUniformLocation * location,GC3Dfloat x,ExceptionCode & ec)3375 void WebGLRenderingContext::uniform1f(const WebGLUniformLocation* location, GC3Dfloat x, ExceptionCode& ec)
3376 {
3377     UNUSED_PARAM(ec);
3378     if (isContextLost() || !location)
3379         return;
3380 
3381     if (location->program() != m_currentProgram) {
3382         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
3383         return;
3384     }
3385 
3386     m_context->uniform1f(location->location(), x);
3387     cleanupAfterGraphicsCall(false);
3388 }
3389 
uniform1fv(const WebGLUniformLocation * location,Float32Array * v,ExceptionCode & ec)3390 void WebGLRenderingContext::uniform1fv(const WebGLUniformLocation* location, Float32Array* v, ExceptionCode& ec)
3391 {
3392     UNUSED_PARAM(ec);
3393     if (isContextLost() || !validateUniformParameters(location, v, 1))
3394         return;
3395 
3396     m_context->uniform1fv(location->location(), v->data(), v->length());
3397     cleanupAfterGraphicsCall(false);
3398 }
3399 
uniform1fv(const WebGLUniformLocation * location,GC3Dfloat * v,GC3Dsizei size,ExceptionCode & ec)3400 void WebGLRenderingContext::uniform1fv(const WebGLUniformLocation* location, GC3Dfloat* v, GC3Dsizei size, ExceptionCode& ec)
3401 {
3402     UNUSED_PARAM(ec);
3403     if (isContextLost() || !validateUniformParameters(location, v, size, 1))
3404         return;
3405 
3406     m_context->uniform1fv(location->location(), v, size);
3407     cleanupAfterGraphicsCall(false);
3408 }
3409 
uniform1i(const WebGLUniformLocation * location,GC3Dint x,ExceptionCode & ec)3410 void WebGLRenderingContext::uniform1i(const WebGLUniformLocation* location, GC3Dint x, ExceptionCode& ec)
3411 {
3412     UNUSED_PARAM(ec);
3413     if (isContextLost() || !location)
3414         return;
3415 
3416     if (location->program() != m_currentProgram) {
3417         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
3418         return;
3419     }
3420 
3421     m_context->uniform1i(location->location(), x);
3422     cleanupAfterGraphicsCall(false);
3423 }
3424 
uniform1iv(const WebGLUniformLocation * location,Int32Array * v,ExceptionCode & ec)3425 void WebGLRenderingContext::uniform1iv(const WebGLUniformLocation* location, Int32Array* v, ExceptionCode& ec)
3426 {
3427     UNUSED_PARAM(ec);
3428     if (isContextLost() || !validateUniformParameters(location, v, 1))
3429         return;
3430 
3431     m_context->uniform1iv(location->location(), v->data(), v->length());
3432     cleanupAfterGraphicsCall(false);
3433 }
3434 
uniform1iv(const WebGLUniformLocation * location,GC3Dint * v,GC3Dsizei size,ExceptionCode & ec)3435 void WebGLRenderingContext::uniform1iv(const WebGLUniformLocation* location, GC3Dint* v, GC3Dsizei size, ExceptionCode& ec)
3436 {
3437     UNUSED_PARAM(ec);
3438     if (isContextLost() || !validateUniformParameters(location, v, size, 1))
3439         return;
3440 
3441     m_context->uniform1iv(location->location(), v, size);
3442     cleanupAfterGraphicsCall(false);
3443 }
3444 
uniform2f(const WebGLUniformLocation * location,GC3Dfloat x,GC3Dfloat y,ExceptionCode & ec)3445 void WebGLRenderingContext::uniform2f(const WebGLUniformLocation* location, GC3Dfloat x, GC3Dfloat y, ExceptionCode& ec)
3446 {
3447     UNUSED_PARAM(ec);
3448     if (isContextLost() || !location)
3449         return;
3450 
3451     if (location->program() != m_currentProgram) {
3452         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
3453         return;
3454     }
3455 
3456     m_context->uniform2f(location->location(), x, y);
3457     cleanupAfterGraphicsCall(false);
3458 }
3459 
uniform2fv(const WebGLUniformLocation * location,Float32Array * v,ExceptionCode & ec)3460 void WebGLRenderingContext::uniform2fv(const WebGLUniformLocation* location, Float32Array* v, ExceptionCode& ec)
3461 {
3462     UNUSED_PARAM(ec);
3463     if (isContextLost() || !validateUniformParameters(location, v, 2))
3464         return;
3465 
3466     m_context->uniform2fv(location->location(), v->data(), v->length() / 2);
3467     cleanupAfterGraphicsCall(false);
3468 }
3469 
uniform2fv(const WebGLUniformLocation * location,GC3Dfloat * v,GC3Dsizei size,ExceptionCode & ec)3470 void WebGLRenderingContext::uniform2fv(const WebGLUniformLocation* location, GC3Dfloat* v, GC3Dsizei size, ExceptionCode& ec)
3471 {
3472     UNUSED_PARAM(ec);
3473     if (isContextLost() || !validateUniformParameters(location, v, size, 2))
3474         return;
3475 
3476     m_context->uniform2fv(location->location(), v, size / 2);
3477     cleanupAfterGraphicsCall(false);
3478 }
3479 
uniform2i(const WebGLUniformLocation * location,GC3Dint x,GC3Dint y,ExceptionCode & ec)3480 void WebGLRenderingContext::uniform2i(const WebGLUniformLocation* location, GC3Dint x, GC3Dint y, ExceptionCode& ec)
3481 {
3482     UNUSED_PARAM(ec);
3483     if (isContextLost() || !location)
3484         return;
3485 
3486     if (location->program() != m_currentProgram) {
3487         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
3488         return;
3489     }
3490 
3491     m_context->uniform2i(location->location(), x, y);
3492     cleanupAfterGraphicsCall(false);
3493 }
3494 
uniform2iv(const WebGLUniformLocation * location,Int32Array * v,ExceptionCode & ec)3495 void WebGLRenderingContext::uniform2iv(const WebGLUniformLocation* location, Int32Array* v, ExceptionCode& ec)
3496 {
3497     UNUSED_PARAM(ec);
3498     if (isContextLost() || !validateUniformParameters(location, v, 2))
3499         return;
3500 
3501     m_context->uniform2iv(location->location(), v->data(), v->length() / 2);
3502     cleanupAfterGraphicsCall(false);
3503 }
3504 
uniform2iv(const WebGLUniformLocation * location,GC3Dint * v,GC3Dsizei size,ExceptionCode & ec)3505 void WebGLRenderingContext::uniform2iv(const WebGLUniformLocation* location, GC3Dint* v, GC3Dsizei size, ExceptionCode& ec)
3506 {
3507     UNUSED_PARAM(ec);
3508     if (isContextLost() || !validateUniformParameters(location, v, size, 2))
3509         return;
3510 
3511     m_context->uniform2iv(location->location(), v, size / 2);
3512     cleanupAfterGraphicsCall(false);
3513 }
3514 
uniform3f(const WebGLUniformLocation * location,GC3Dfloat x,GC3Dfloat y,GC3Dfloat z,ExceptionCode & ec)3515 void WebGLRenderingContext::uniform3f(const WebGLUniformLocation* location, GC3Dfloat x, GC3Dfloat y, GC3Dfloat z, ExceptionCode& ec)
3516 {
3517     UNUSED_PARAM(ec);
3518     if (isContextLost() || !location)
3519         return;
3520 
3521     if (location->program() != m_currentProgram) {
3522         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
3523         return;
3524     }
3525 
3526     m_context->uniform3f(location->location(), x, y, z);
3527     cleanupAfterGraphicsCall(false);
3528 }
3529 
uniform3fv(const WebGLUniformLocation * location,Float32Array * v,ExceptionCode & ec)3530 void WebGLRenderingContext::uniform3fv(const WebGLUniformLocation* location, Float32Array* v, ExceptionCode& ec)
3531 {
3532     UNUSED_PARAM(ec);
3533     if (isContextLost() || !validateUniformParameters(location, v, 3))
3534         return;
3535 
3536     m_context->uniform3fv(location->location(), v->data(), v->length() / 3);
3537     cleanupAfterGraphicsCall(false);
3538 }
3539 
uniform3fv(const WebGLUniformLocation * location,GC3Dfloat * v,GC3Dsizei size,ExceptionCode & ec)3540 void WebGLRenderingContext::uniform3fv(const WebGLUniformLocation* location, GC3Dfloat* v, GC3Dsizei size, ExceptionCode& ec)
3541 {
3542     UNUSED_PARAM(ec);
3543     if (isContextLost() || !validateUniformParameters(location, v, size, 3))
3544         return;
3545 
3546     m_context->uniform3fv(location->location(), v, size / 3);
3547     cleanupAfterGraphicsCall(false);
3548 }
3549 
uniform3i(const WebGLUniformLocation * location,GC3Dint x,GC3Dint y,GC3Dint z,ExceptionCode & ec)3550 void WebGLRenderingContext::uniform3i(const WebGLUniformLocation* location, GC3Dint x, GC3Dint y, GC3Dint z, ExceptionCode& ec)
3551 {
3552     UNUSED_PARAM(ec);
3553     if (isContextLost() || !location)
3554         return;
3555 
3556     if (location->program() != m_currentProgram) {
3557         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
3558         return;
3559     }
3560 
3561     m_context->uniform3i(location->location(), x, y, z);
3562     cleanupAfterGraphicsCall(false);
3563 }
3564 
uniform3iv(const WebGLUniformLocation * location,Int32Array * v,ExceptionCode & ec)3565 void WebGLRenderingContext::uniform3iv(const WebGLUniformLocation* location, Int32Array* v, ExceptionCode& ec)
3566 {
3567     UNUSED_PARAM(ec);
3568     if (isContextLost() || !validateUniformParameters(location, v, 3))
3569         return;
3570 
3571     m_context->uniform3iv(location->location(), v->data(), v->length() / 3);
3572     cleanupAfterGraphicsCall(false);
3573 }
3574 
uniform3iv(const WebGLUniformLocation * location,GC3Dint * v,GC3Dsizei size,ExceptionCode & ec)3575 void WebGLRenderingContext::uniform3iv(const WebGLUniformLocation* location, GC3Dint* v, GC3Dsizei size, ExceptionCode& ec)
3576 {
3577     UNUSED_PARAM(ec);
3578     if (isContextLost() || !validateUniformParameters(location, v, size, 3))
3579         return;
3580 
3581     m_context->uniform3iv(location->location(), v, size / 3);
3582     cleanupAfterGraphicsCall(false);
3583 }
3584 
uniform4f(const WebGLUniformLocation * location,GC3Dfloat x,GC3Dfloat y,GC3Dfloat z,GC3Dfloat w,ExceptionCode & ec)3585 void WebGLRenderingContext::uniform4f(const WebGLUniformLocation* location, GC3Dfloat x, GC3Dfloat y, GC3Dfloat z, GC3Dfloat w, ExceptionCode& ec)
3586 {
3587     UNUSED_PARAM(ec);
3588     if (isContextLost() || !location)
3589         return;
3590 
3591     if (location->program() != m_currentProgram) {
3592         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
3593         return;
3594     }
3595 
3596     m_context->uniform4f(location->location(), x, y, z, w);
3597     cleanupAfterGraphicsCall(false);
3598 }
3599 
uniform4fv(const WebGLUniformLocation * location,Float32Array * v,ExceptionCode & ec)3600 void WebGLRenderingContext::uniform4fv(const WebGLUniformLocation* location, Float32Array* v, ExceptionCode& ec)
3601 {
3602     UNUSED_PARAM(ec);
3603     if (isContextLost() || !validateUniformParameters(location, v, 4))
3604         return;
3605 
3606     m_context->uniform4fv(location->location(), v->data(), v->length() / 4);
3607     cleanupAfterGraphicsCall(false);
3608 }
3609 
uniform4fv(const WebGLUniformLocation * location,GC3Dfloat * v,GC3Dsizei size,ExceptionCode & ec)3610 void WebGLRenderingContext::uniform4fv(const WebGLUniformLocation* location, GC3Dfloat* v, GC3Dsizei size, ExceptionCode& ec)
3611 {
3612     UNUSED_PARAM(ec);
3613     if (isContextLost() || !validateUniformParameters(location, v, size, 4))
3614         return;
3615 
3616     m_context->uniform4fv(location->location(), v, size / 4);
3617     cleanupAfterGraphicsCall(false);
3618 }
3619 
uniform4i(const WebGLUniformLocation * location,GC3Dint x,GC3Dint y,GC3Dint z,GC3Dint w,ExceptionCode & ec)3620 void WebGLRenderingContext::uniform4i(const WebGLUniformLocation* location, GC3Dint x, GC3Dint y, GC3Dint z, GC3Dint w, ExceptionCode& ec)
3621 {
3622     UNUSED_PARAM(ec);
3623     if (isContextLost() || !location)
3624         return;
3625 
3626     if (location->program() != m_currentProgram) {
3627         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
3628         return;
3629     }
3630 
3631     m_context->uniform4i(location->location(), x, y, z, w);
3632     cleanupAfterGraphicsCall(false);
3633 }
3634 
uniform4iv(const WebGLUniformLocation * location,Int32Array * v,ExceptionCode & ec)3635 void WebGLRenderingContext::uniform4iv(const WebGLUniformLocation* location, Int32Array* v, ExceptionCode& ec)
3636 {
3637     UNUSED_PARAM(ec);
3638     if (isContextLost() || !validateUniformParameters(location, v, 4))
3639         return;
3640 
3641     m_context->uniform4iv(location->location(), v->data(), v->length() / 4);
3642     cleanupAfterGraphicsCall(false);
3643 }
3644 
uniform4iv(const WebGLUniformLocation * location,GC3Dint * v,GC3Dsizei size,ExceptionCode & ec)3645 void WebGLRenderingContext::uniform4iv(const WebGLUniformLocation* location, GC3Dint* v, GC3Dsizei size, ExceptionCode& ec)
3646 {
3647     UNUSED_PARAM(ec);
3648     if (isContextLost() || !validateUniformParameters(location, v, size, 4))
3649         return;
3650 
3651     m_context->uniform4iv(location->location(), v, size / 4);
3652     cleanupAfterGraphicsCall(false);
3653 }
3654 
uniformMatrix2fv(const WebGLUniformLocation * location,GC3Dboolean transpose,Float32Array * v,ExceptionCode & ec)3655 void WebGLRenderingContext::uniformMatrix2fv(const WebGLUniformLocation* location, GC3Dboolean transpose, Float32Array* v, ExceptionCode& ec)
3656 {
3657     UNUSED_PARAM(ec);
3658     if (isContextLost() || !validateUniformMatrixParameters(location, transpose, v, 4))
3659         return;
3660     m_context->uniformMatrix2fv(location->location(), transpose, v->data(), v->length() / 4);
3661     cleanupAfterGraphicsCall(false);
3662 }
3663 
uniformMatrix2fv(const WebGLUniformLocation * location,GC3Dboolean transpose,GC3Dfloat * v,GC3Dsizei size,ExceptionCode & ec)3664 void WebGLRenderingContext::uniformMatrix2fv(const WebGLUniformLocation* location, GC3Dboolean transpose, GC3Dfloat* v, GC3Dsizei size, ExceptionCode& ec)
3665 {
3666     UNUSED_PARAM(ec);
3667     if (isContextLost() || !validateUniformMatrixParameters(location, transpose, v, size, 4))
3668         return;
3669     m_context->uniformMatrix2fv(location->location(), transpose, v, size / 4);
3670     cleanupAfterGraphicsCall(false);
3671 }
3672 
uniformMatrix3fv(const WebGLUniformLocation * location,GC3Dboolean transpose,Float32Array * v,ExceptionCode & ec)3673 void WebGLRenderingContext::uniformMatrix3fv(const WebGLUniformLocation* location, GC3Dboolean transpose, Float32Array* v, ExceptionCode& ec)
3674 {
3675     UNUSED_PARAM(ec);
3676     if (isContextLost() || !validateUniformMatrixParameters(location, transpose, v, 9))
3677         return;
3678     m_context->uniformMatrix3fv(location->location(), transpose, v->data(), v->length() / 9);
3679     cleanupAfterGraphicsCall(false);
3680 }
3681 
uniformMatrix3fv(const WebGLUniformLocation * location,GC3Dboolean transpose,GC3Dfloat * v,GC3Dsizei size,ExceptionCode & ec)3682 void WebGLRenderingContext::uniformMatrix3fv(const WebGLUniformLocation* location, GC3Dboolean transpose, GC3Dfloat* v, GC3Dsizei size, ExceptionCode& ec)
3683 {
3684     UNUSED_PARAM(ec);
3685     if (isContextLost() || !validateUniformMatrixParameters(location, transpose, v, size, 9))
3686         return;
3687     m_context->uniformMatrix3fv(location->location(), transpose, v, size / 9);
3688     cleanupAfterGraphicsCall(false);
3689 }
3690 
uniformMatrix4fv(const WebGLUniformLocation * location,GC3Dboolean transpose,Float32Array * v,ExceptionCode & ec)3691 void WebGLRenderingContext::uniformMatrix4fv(const WebGLUniformLocation* location, GC3Dboolean transpose, Float32Array* v, ExceptionCode& ec)
3692 {
3693     UNUSED_PARAM(ec);
3694     if (isContextLost() || !validateUniformMatrixParameters(location, transpose, v, 16))
3695         return;
3696     m_context->uniformMatrix4fv(location->location(), transpose, v->data(), v->length() / 16);
3697     cleanupAfterGraphicsCall(false);
3698 }
3699 
uniformMatrix4fv(const WebGLUniformLocation * location,GC3Dboolean transpose,GC3Dfloat * v,GC3Dsizei size,ExceptionCode & ec)3700 void WebGLRenderingContext::uniformMatrix4fv(const WebGLUniformLocation* location, GC3Dboolean transpose, GC3Dfloat* v, GC3Dsizei size, ExceptionCode& ec)
3701 {
3702     UNUSED_PARAM(ec);
3703     if (isContextLost() || !validateUniformMatrixParameters(location, transpose, v, size, 16))
3704         return;
3705     m_context->uniformMatrix4fv(location->location(), transpose, v, size / 16);
3706     cleanupAfterGraphicsCall(false);
3707 }
3708 
useProgram(WebGLProgram * program,ExceptionCode & ec)3709 void WebGLRenderingContext::useProgram(WebGLProgram* program, ExceptionCode& ec)
3710 {
3711     UNUSED_PARAM(ec);
3712     bool deleted;
3713     if (!checkObjectToBeBound(program, deleted))
3714         return;
3715     if (deleted)
3716         program = 0;
3717     if (program && !program->getLinkStatus()) {
3718         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
3719         cleanupAfterGraphicsCall(false);
3720         return;
3721     }
3722     if (m_currentProgram != program) {
3723         if (m_currentProgram)
3724             m_currentProgram->onDetached();
3725         m_currentProgram = program;
3726         m_context->useProgram(objectOrZero(program));
3727         if (program)
3728             program->onAttached();
3729     }
3730     cleanupAfterGraphicsCall(false);
3731 }
3732 
validateProgram(WebGLProgram * program,ExceptionCode & ec)3733 void WebGLRenderingContext::validateProgram(WebGLProgram* program, ExceptionCode& ec)
3734 {
3735     UNUSED_PARAM(ec);
3736     if (isContextLost() || !validateWebGLObject(program))
3737         return;
3738     m_context->validateProgram(objectOrZero(program));
3739     cleanupAfterGraphicsCall(false);
3740 }
3741 
vertexAttrib1f(GC3Duint index,GC3Dfloat v0)3742 void WebGLRenderingContext::vertexAttrib1f(GC3Duint index, GC3Dfloat v0)
3743 {
3744     vertexAttribfImpl(index, 1, v0, 0.0f, 0.0f, 1.0f);
3745 }
3746 
vertexAttrib1fv(GC3Duint index,Float32Array * v)3747 void WebGLRenderingContext::vertexAttrib1fv(GC3Duint index, Float32Array* v)
3748 {
3749     vertexAttribfvImpl(index, v, 1);
3750 }
3751 
vertexAttrib1fv(GC3Duint index,GC3Dfloat * v,GC3Dsizei size)3752 void WebGLRenderingContext::vertexAttrib1fv(GC3Duint index, GC3Dfloat* v, GC3Dsizei size)
3753 {
3754     vertexAttribfvImpl(index, v, size, 1);
3755 }
3756 
vertexAttrib2f(GC3Duint index,GC3Dfloat v0,GC3Dfloat v1)3757 void WebGLRenderingContext::vertexAttrib2f(GC3Duint index, GC3Dfloat v0, GC3Dfloat v1)
3758 {
3759     vertexAttribfImpl(index, 2, v0, v1, 0.0f, 1.0f);
3760 }
3761 
vertexAttrib2fv(GC3Duint index,Float32Array * v)3762 void WebGLRenderingContext::vertexAttrib2fv(GC3Duint index, Float32Array* v)
3763 {
3764     vertexAttribfvImpl(index, v, 2);
3765 }
3766 
vertexAttrib2fv(GC3Duint index,GC3Dfloat * v,GC3Dsizei size)3767 void WebGLRenderingContext::vertexAttrib2fv(GC3Duint index, GC3Dfloat* v, GC3Dsizei size)
3768 {
3769     vertexAttribfvImpl(index, v, size, 2);
3770 }
3771 
vertexAttrib3f(GC3Duint index,GC3Dfloat v0,GC3Dfloat v1,GC3Dfloat v2)3772 void WebGLRenderingContext::vertexAttrib3f(GC3Duint index, GC3Dfloat v0, GC3Dfloat v1, GC3Dfloat v2)
3773 {
3774     vertexAttribfImpl(index, 3, v0, v1, v2, 1.0f);
3775 }
3776 
vertexAttrib3fv(GC3Duint index,Float32Array * v)3777 void WebGLRenderingContext::vertexAttrib3fv(GC3Duint index, Float32Array* v)
3778 {
3779     vertexAttribfvImpl(index, v, 3);
3780 }
3781 
vertexAttrib3fv(GC3Duint index,GC3Dfloat * v,GC3Dsizei size)3782 void WebGLRenderingContext::vertexAttrib3fv(GC3Duint index, GC3Dfloat* v, GC3Dsizei size)
3783 {
3784     vertexAttribfvImpl(index, v, size, 3);
3785 }
3786 
vertexAttrib4f(GC3Duint index,GC3Dfloat v0,GC3Dfloat v1,GC3Dfloat v2,GC3Dfloat v3)3787 void WebGLRenderingContext::vertexAttrib4f(GC3Duint index, GC3Dfloat v0, GC3Dfloat v1, GC3Dfloat v2, GC3Dfloat v3)
3788 {
3789     vertexAttribfImpl(index, 4, v0, v1, v2, v3);
3790 }
3791 
vertexAttrib4fv(GC3Duint index,Float32Array * v)3792 void WebGLRenderingContext::vertexAttrib4fv(GC3Duint index, Float32Array* v)
3793 {
3794     vertexAttribfvImpl(index, v, 4);
3795 }
3796 
vertexAttrib4fv(GC3Duint index,GC3Dfloat * v,GC3Dsizei size)3797 void WebGLRenderingContext::vertexAttrib4fv(GC3Duint index, GC3Dfloat* v, GC3Dsizei size)
3798 {
3799     vertexAttribfvImpl(index, v, size, 4);
3800 }
3801 
vertexAttribPointer(GC3Duint index,GC3Dint size,GC3Denum type,GC3Dboolean normalized,GC3Dsizei stride,GC3Dintptr offset,ExceptionCode & ec)3802 void WebGLRenderingContext::vertexAttribPointer(GC3Duint index, GC3Dint size, GC3Denum type, GC3Dboolean normalized, GC3Dsizei stride, GC3Dintptr offset, ExceptionCode& ec)
3803 {
3804     UNUSED_PARAM(ec);
3805     if (isContextLost())
3806         return;
3807     switch (type) {
3808     case GraphicsContext3D::BYTE:
3809     case GraphicsContext3D::UNSIGNED_BYTE:
3810     case GraphicsContext3D::SHORT:
3811     case GraphicsContext3D::UNSIGNED_SHORT:
3812     case GraphicsContext3D::FLOAT:
3813         break;
3814     default:
3815         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
3816         return;
3817     }
3818     if (index >= m_maxVertexAttribs) {
3819         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
3820         return;
3821     }
3822     if (size < 1 || size > 4 || stride < 0 || stride > 255 || offset < 0) {
3823         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
3824         return;
3825     }
3826     if (!m_boundArrayBuffer) {
3827         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
3828         return;
3829     }
3830     // Determine the number of elements the bound buffer can hold, given the offset, size, type and stride
3831     unsigned int typeSize = sizeInBytes(type);
3832     if (!typeSize) {
3833         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
3834         return;
3835     }
3836     if ((stride % typeSize) || (offset % typeSize)) {
3837         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
3838         return;
3839     }
3840     GC3Dsizei bytesPerElement = size * typeSize;
3841 
3842     GC3Dsizei validatedStride = stride ? stride : bytesPerElement;
3843 
3844     WebGLVertexArrayObjectOES::VertexAttribState& state = m_boundVertexArrayObject->getVertexAttribState(index);
3845     state.bufferBinding = m_boundArrayBuffer;
3846     state.bytesPerElement = bytesPerElement;
3847     state.size = size;
3848     state.type = type;
3849     state.normalized = normalized;
3850     state.stride = validatedStride;
3851     state.originalStride = stride;
3852     state.offset = offset;
3853     m_context->vertexAttribPointer(index, size, type, normalized, stride, offset);
3854     cleanupAfterGraphicsCall(false);
3855 }
3856 
viewport(GC3Dint x,GC3Dint y,GC3Dsizei width,GC3Dsizei height)3857 void WebGLRenderingContext::viewport(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height)
3858 {
3859     if (isContextLost())
3860         return;
3861     if (isnan(x))
3862         x = 0;
3863     if (isnan(y))
3864         y = 0;
3865     if (isnan(width))
3866         width = 100;
3867     if (isnan(height))
3868         height = 100;
3869     if (!validateSize(width, height))
3870         return;
3871     m_context->viewport(x, y, width, height);
3872     cleanupAfterGraphicsCall(false);
3873 }
3874 
forceLostContext()3875 void WebGLRenderingContext::forceLostContext()
3876 {
3877     if (isContextLost()) {
3878         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
3879         return;
3880     }
3881 
3882     m_restoreTimer.startOneShot(0);
3883 }
3884 
onLostContext()3885 void WebGLRenderingContext::onLostContext()
3886 {
3887     m_contextLost = true;
3888 
3889     detachAndRemoveAllObjects();
3890 
3891     // There is no direct way to clear errors from a GL implementation and
3892     // looping until getError() becomes NO_ERROR might cause an infinite loop if
3893     // the driver or context implementation had a bug.  So, loop a reasonably
3894     // large number of times to clear any existing errors.
3895     for (int i = 0; i < 100; ++i) {
3896         if (m_context->getError() == GraphicsContext3D::NO_ERROR)
3897             break;
3898     }
3899     m_context->synthesizeGLError(GraphicsContext3D::CONTEXT_LOST_WEBGL);
3900 
3901     canvas()->dispatchEvent(WebGLContextEvent::create(eventNames().webglcontextlostEvent, false, true, ""));
3902 }
3903 
restoreContext()3904 void WebGLRenderingContext::restoreContext()
3905 {
3906     RefPtr<GraphicsContext3D> context(GraphicsContext3D::create(m_attributes, canvas()->document()->view()->root()->hostWindow()));
3907     if (!context)
3908         return;
3909 
3910     m_context = context;
3911     m_contextLost = false;
3912     initializeNewContext();
3913     canvas()->dispatchEvent(WebGLContextEvent::create(eventNames().webglcontextrestoredEvent, false, true, ""));
3914 }
3915 
removeObject(WebGLObject * object)3916 void WebGLRenderingContext::removeObject(WebGLObject* object)
3917 {
3918     m_canvasObjects.remove(object);
3919 }
3920 
addObject(WebGLObject * object)3921 void WebGLRenderingContext::addObject(WebGLObject* object)
3922 {
3923     ASSERT(!isContextLost());
3924     removeObject(object);
3925     m_canvasObjects.add(object);
3926 }
3927 
detachAndRemoveAllObjects()3928 void WebGLRenderingContext::detachAndRemoveAllObjects()
3929 {
3930     HashSet<RefPtr<WebGLObject> >::iterator pend = m_canvasObjects.end();
3931     for (HashSet<RefPtr<WebGLObject> >::iterator it = m_canvasObjects.begin(); it != pend; ++it)
3932         (*it)->detachContext();
3933 
3934     m_canvasObjects.clear();
3935 }
3936 
findTexture(Platform3DObject obj)3937 WebGLTexture* WebGLRenderingContext::findTexture(Platform3DObject obj)
3938 {
3939     if (!obj)
3940         return 0;
3941     HashSet<RefPtr<WebGLObject> >::iterator pend = m_canvasObjects.end();
3942     for (HashSet<RefPtr<WebGLObject> >::iterator it = m_canvasObjects.begin(); it != pend; ++it) {
3943         if ((*it)->isTexture() && (*it)->object() == obj)
3944             return reinterpret_cast<WebGLTexture*>((*it).get());
3945     }
3946     return 0;
3947 }
3948 
findRenderbuffer(Platform3DObject obj)3949 WebGLRenderbuffer* WebGLRenderingContext::findRenderbuffer(Platform3DObject obj)
3950 {
3951     if (!obj)
3952         return 0;
3953     HashSet<RefPtr<WebGLObject> >::iterator pend = m_canvasObjects.end();
3954     for (HashSet<RefPtr<WebGLObject> >::iterator it = m_canvasObjects.begin(); it != pend; ++it) {
3955         if ((*it)->isRenderbuffer() && (*it)->object() == obj)
3956             return reinterpret_cast<WebGLRenderbuffer*>((*it).get());
3957     }
3958     return 0;
3959 }
3960 
findBuffer(Platform3DObject obj)3961 WebGLBuffer* WebGLRenderingContext::findBuffer(Platform3DObject obj)
3962 {
3963     if (!obj)
3964         return 0;
3965     HashSet<RefPtr<WebGLObject> >::iterator pend = m_canvasObjects.end();
3966     for (HashSet<RefPtr<WebGLObject> >::iterator it = m_canvasObjects.begin(); it != pend; ++it) {
3967         if ((*it)->isBuffer() && (*it)->object() == obj)
3968             return reinterpret_cast<WebGLBuffer*>((*it).get());
3969     }
3970     return 0;
3971 }
3972 
findShader(Platform3DObject obj)3973 WebGLShader* WebGLRenderingContext::findShader(Platform3DObject obj)
3974 {
3975     if (!obj)
3976         return 0;
3977     HashSet<RefPtr<WebGLObject> >::iterator pend = m_canvasObjects.end();
3978     for (HashSet<RefPtr<WebGLObject> >::iterator it = m_canvasObjects.begin(); it != pend; ++it) {
3979         if ((*it)->isShader() && (*it)->object() == obj)
3980             return reinterpret_cast<WebGLShader*>((*it).get());
3981     }
3982     return 0;
3983 }
3984 
getBooleanParameter(GC3Denum pname)3985 WebGLGetInfo WebGLRenderingContext::getBooleanParameter(GC3Denum pname)
3986 {
3987     GC3Dboolean value = 0;
3988     m_context->getBooleanv(pname, &value);
3989     return WebGLGetInfo(static_cast<bool>(value));
3990 }
3991 
getBooleanArrayParameter(GC3Denum pname)3992 WebGLGetInfo WebGLRenderingContext::getBooleanArrayParameter(GC3Denum pname)
3993 {
3994     if (pname != GraphicsContext3D::COLOR_WRITEMASK) {
3995         notImplemented();
3996         return WebGLGetInfo(0, 0);
3997     }
3998     GC3Dboolean value[4] = {0};
3999     m_context->getBooleanv(pname, value);
4000     bool boolValue[4];
4001     for (int ii = 0; ii < 4; ++ii)
4002         boolValue[ii] = static_cast<bool>(value[ii]);
4003     return WebGLGetInfo(boolValue, 4);
4004 }
4005 
getFloatParameter(GC3Denum pname)4006 WebGLGetInfo WebGLRenderingContext::getFloatParameter(GC3Denum pname)
4007 {
4008     GC3Dfloat value = 0;
4009     m_context->getFloatv(pname, &value);
4010     return WebGLGetInfo(value);
4011 }
4012 
getIntParameter(GC3Denum pname)4013 WebGLGetInfo WebGLRenderingContext::getIntParameter(GC3Denum pname)
4014 {
4015     GC3Dint value = 0;
4016     m_context->getIntegerv(pname, &value);
4017     return WebGLGetInfo(value);
4018 }
4019 
getUnsignedIntParameter(GC3Denum pname)4020 WebGLGetInfo WebGLRenderingContext::getUnsignedIntParameter(GC3Denum pname)
4021 {
4022     GC3Dint value = 0;
4023     m_context->getIntegerv(pname, &value);
4024     return WebGLGetInfo(static_cast<unsigned int>(value));
4025 }
4026 
getWebGLFloatArrayParameter(GC3Denum pname)4027 WebGLGetInfo WebGLRenderingContext::getWebGLFloatArrayParameter(GC3Denum pname)
4028 {
4029     GC3Dfloat value[4] = {0};
4030     m_context->getFloatv(pname, value);
4031     unsigned length = 0;
4032     switch (pname) {
4033     case GraphicsContext3D::ALIASED_POINT_SIZE_RANGE:
4034     case GraphicsContext3D::ALIASED_LINE_WIDTH_RANGE:
4035     case GraphicsContext3D::DEPTH_RANGE:
4036         length = 2;
4037         break;
4038     case GraphicsContext3D::BLEND_COLOR:
4039     case GraphicsContext3D::COLOR_CLEAR_VALUE:
4040         length = 4;
4041         break;
4042     default:
4043         notImplemented();
4044     }
4045     return WebGLGetInfo(Float32Array::create(value, length));
4046 }
4047 
getWebGLIntArrayParameter(GC3Denum pname)4048 WebGLGetInfo WebGLRenderingContext::getWebGLIntArrayParameter(GC3Denum pname)
4049 {
4050     GC3Dint value[4] = {0};
4051     m_context->getIntegerv(pname, value);
4052     unsigned length = 0;
4053     switch (pname) {
4054     case GraphicsContext3D::MAX_VIEWPORT_DIMS:
4055         length = 2;
4056         break;
4057     case GraphicsContext3D::SCISSOR_BOX:
4058     case GraphicsContext3D::VIEWPORT:
4059         length = 4;
4060         break;
4061     default:
4062         notImplemented();
4063     }
4064     return WebGLGetInfo(Int32Array::create(value, length));
4065 }
4066 
handleNPOTTextures(bool prepareToDraw)4067 void WebGLRenderingContext::handleNPOTTextures(bool prepareToDraw)
4068 {
4069     bool resetActiveUnit = false;
4070     for (unsigned ii = 0; ii < m_textureUnits.size(); ++ii) {
4071         if ((m_textureUnits[ii].m_texture2DBinding && m_textureUnits[ii].m_texture2DBinding->needToUseBlackTexture())
4072             || (m_textureUnits[ii].m_textureCubeMapBinding && m_textureUnits[ii].m_textureCubeMapBinding->needToUseBlackTexture())) {
4073             if (ii != m_activeTextureUnit) {
4074                 m_context->activeTexture(ii);
4075                 resetActiveUnit = true;
4076             } else if (resetActiveUnit) {
4077                 m_context->activeTexture(ii);
4078                 resetActiveUnit = false;
4079             }
4080             WebGLTexture* tex2D;
4081             WebGLTexture* texCubeMap;
4082             if (prepareToDraw) {
4083                 tex2D = m_blackTexture2D.get();
4084                 texCubeMap = m_blackTextureCubeMap.get();
4085             } else {
4086                 tex2D = m_textureUnits[ii].m_texture2DBinding.get();
4087                 texCubeMap = m_textureUnits[ii].m_textureCubeMapBinding.get();
4088             }
4089             if (m_textureUnits[ii].m_texture2DBinding && m_textureUnits[ii].m_texture2DBinding->needToUseBlackTexture())
4090                 m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, objectOrZero(tex2D));
4091             if (m_textureUnits[ii].m_textureCubeMapBinding && m_textureUnits[ii].m_textureCubeMapBinding->needToUseBlackTexture())
4092                 m_context->bindTexture(GraphicsContext3D::TEXTURE_CUBE_MAP, objectOrZero(texCubeMap));
4093         }
4094     }
4095     if (resetActiveUnit)
4096         m_context->activeTexture(m_activeTextureUnit);
4097 }
4098 
createFallbackBlackTextures1x1()4099 void WebGLRenderingContext::createFallbackBlackTextures1x1()
4100 {
4101     unsigned char black[] = {0, 0, 0, 255};
4102     m_blackTexture2D = createTexture();
4103     m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_blackTexture2D->object());
4104     m_context->texImage2D(GraphicsContext3D::TEXTURE_2D, 0, GraphicsContext3D::RGBA, 1, 1,
4105                           0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, black);
4106     m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, 0);
4107     m_blackTextureCubeMap = createTexture();
4108     m_context->bindTexture(GraphicsContext3D::TEXTURE_CUBE_MAP, m_blackTextureCubeMap->object());
4109     m_context->texImage2D(GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_X, 0, GraphicsContext3D::RGBA, 1, 1,
4110                           0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, black);
4111     m_context->texImage2D(GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GraphicsContext3D::RGBA, 1, 1,
4112                           0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, black);
4113     m_context->texImage2D(GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GraphicsContext3D::RGBA, 1, 1,
4114                           0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, black);
4115     m_context->texImage2D(GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GraphicsContext3D::RGBA, 1, 1,
4116                           0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, black);
4117     m_context->texImage2D(GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GraphicsContext3D::RGBA, 1, 1,
4118                           0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, black);
4119     m_context->texImage2D(GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GraphicsContext3D::RGBA, 1, 1,
4120                           0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, black);
4121     m_context->bindTexture(GraphicsContext3D::TEXTURE_CUBE_MAP, 0);
4122 }
4123 
isTexInternalFormatColorBufferCombinationValid(GC3Denum texInternalFormat,GC3Denum colorBufferFormat)4124 bool WebGLRenderingContext::isTexInternalFormatColorBufferCombinationValid(GC3Denum texInternalFormat,
4125                                                                            GC3Denum colorBufferFormat)
4126 {
4127     switch (colorBufferFormat) {
4128     case GraphicsContext3D::ALPHA:
4129         if (texInternalFormat == GraphicsContext3D::ALPHA)
4130             return true;
4131         break;
4132     case GraphicsContext3D::RGB:
4133         if (texInternalFormat == GraphicsContext3D::LUMINANCE
4134             || texInternalFormat == GraphicsContext3D::RGB)
4135             return true;
4136         break;
4137     case GraphicsContext3D::RGBA:
4138         return true;
4139     }
4140     return false;
4141 }
4142 
getBoundFramebufferColorFormat()4143 GC3Denum WebGLRenderingContext::getBoundFramebufferColorFormat()
4144 {
4145     if (m_framebufferBinding && m_framebufferBinding->object())
4146         return m_framebufferBinding->getColorBufferFormat();
4147     if (m_attributes.alpha)
4148         return GraphicsContext3D::RGBA;
4149     return GraphicsContext3D::RGB;
4150 }
4151 
getBoundFramebufferWidth()4152 int WebGLRenderingContext::getBoundFramebufferWidth()
4153 {
4154     if (m_framebufferBinding && m_framebufferBinding->object())
4155         return m_framebufferBinding->getWidth();
4156     return m_context->getInternalFramebufferSize().width();
4157 }
4158 
getBoundFramebufferHeight()4159 int WebGLRenderingContext::getBoundFramebufferHeight()
4160 {
4161     if (m_framebufferBinding && m_framebufferBinding->object())
4162         return m_framebufferBinding->getHeight();
4163     return m_context->getInternalFramebufferSize().height();
4164 }
4165 
validateTextureBinding(GC3Denum target,bool useSixEnumsForCubeMap)4166 WebGLTexture* WebGLRenderingContext::validateTextureBinding(GC3Denum target, bool useSixEnumsForCubeMap)
4167 {
4168     WebGLTexture* tex = 0;
4169     switch (target) {
4170     case GraphicsContext3D::TEXTURE_2D:
4171         tex = m_textureUnits[m_activeTextureUnit].m_texture2DBinding.get();
4172         break;
4173     case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_X:
4174     case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_X:
4175     case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Y:
4176     case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Y:
4177     case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Z:
4178     case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Z:
4179         if (!useSixEnumsForCubeMap) {
4180             m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
4181             return 0;
4182         }
4183         tex = m_textureUnits[m_activeTextureUnit].m_textureCubeMapBinding.get();
4184         break;
4185     case GraphicsContext3D::TEXTURE_CUBE_MAP:
4186         if (useSixEnumsForCubeMap) {
4187             m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
4188             return 0;
4189         }
4190         tex = m_textureUnits[m_activeTextureUnit].m_textureCubeMapBinding.get();
4191         break;
4192     default:
4193         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
4194         return 0;
4195     }
4196     if (!tex)
4197         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
4198     return tex;
4199 }
4200 
validateSize(GC3Dint x,GC3Dint y)4201 bool WebGLRenderingContext::validateSize(GC3Dint x, GC3Dint y)
4202 {
4203     if (x < 0 || y < 0) {
4204         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
4205         return false;
4206     }
4207     return true;
4208 }
4209 
validateString(const String & string)4210 bool WebGLRenderingContext::validateString(const String& string)
4211 {
4212     for (size_t i = 0; i < string.length(); ++i) {
4213         if (!validateCharacter(string[i])) {
4214             m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
4215             return false;
4216         }
4217     }
4218     return true;
4219 }
4220 
validateTexFuncFormatAndType(GC3Denum format,GC3Denum type)4221 bool WebGLRenderingContext::validateTexFuncFormatAndType(GC3Denum format, GC3Denum type)
4222 {
4223     switch (format) {
4224     case GraphicsContext3D::ALPHA:
4225     case GraphicsContext3D::LUMINANCE:
4226     case GraphicsContext3D::LUMINANCE_ALPHA:
4227     case GraphicsContext3D::RGB:
4228     case GraphicsContext3D::RGBA:
4229         break;
4230     default:
4231         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
4232         return false;
4233     }
4234 
4235     switch (type) {
4236     case GraphicsContext3D::UNSIGNED_BYTE:
4237     case GraphicsContext3D::UNSIGNED_SHORT_5_6_5:
4238     case GraphicsContext3D::UNSIGNED_SHORT_4_4_4_4:
4239     case GraphicsContext3D::UNSIGNED_SHORT_5_5_5_1:
4240         break;
4241     case GraphicsContext3D::FLOAT:
4242         if (m_oesTextureFloat)
4243             break;
4244         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
4245         return false;
4246     default:
4247         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
4248         return false;
4249     }
4250 
4251     // Verify that the combination of format and type is supported.
4252     switch (format) {
4253     case GraphicsContext3D::ALPHA:
4254     case GraphicsContext3D::LUMINANCE:
4255     case GraphicsContext3D::LUMINANCE_ALPHA:
4256         if (type != GraphicsContext3D::UNSIGNED_BYTE
4257             && type != GraphicsContext3D::FLOAT) {
4258             m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
4259             return false;
4260         }
4261         break;
4262     case GraphicsContext3D::RGB:
4263         if (type != GraphicsContext3D::UNSIGNED_BYTE
4264             && type != GraphicsContext3D::UNSIGNED_SHORT_5_6_5
4265             && type != GraphicsContext3D::FLOAT) {
4266             m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
4267             return false;
4268         }
4269         break;
4270     case GraphicsContext3D::RGBA:
4271         if (type != GraphicsContext3D::UNSIGNED_BYTE
4272             && type != GraphicsContext3D::UNSIGNED_SHORT_4_4_4_4
4273             && type != GraphicsContext3D::UNSIGNED_SHORT_5_5_5_1
4274             && type != GraphicsContext3D::FLOAT) {
4275             m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
4276             return false;
4277         }
4278         break;
4279     default:
4280         ASSERT_NOT_REACHED();
4281     }
4282 
4283     return true;
4284 }
4285 
validateTexFuncLevel(GC3Denum target,GC3Dint level)4286 bool WebGLRenderingContext::validateTexFuncLevel(GC3Denum target, GC3Dint level)
4287 {
4288     if (level < 0) {
4289         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
4290         return false;
4291     }
4292     switch (target) {
4293     case GraphicsContext3D::TEXTURE_2D:
4294         if (level > m_maxTextureLevel) {
4295             m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
4296             return false;
4297         }
4298         break;
4299     case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_X:
4300     case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_X:
4301     case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Y:
4302     case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Y:
4303     case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Z:
4304     case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Z:
4305         if (level > m_maxCubeMapTextureLevel) {
4306             m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
4307             return false;
4308         }
4309         break;
4310     }
4311     // This function only checks if level is legal, so we return true and don't
4312     // generate INVALID_ENUM if target is illegal.
4313     return true;
4314 }
4315 
validateTexFuncParameters(GC3Denum target,GC3Dint level,GC3Denum internalformat,GC3Dsizei width,GC3Dsizei height,GC3Dint border,GC3Denum format,GC3Denum type)4316 bool WebGLRenderingContext::validateTexFuncParameters(GC3Denum target, GC3Dint level,
4317                                                       GC3Denum internalformat,
4318                                                       GC3Dsizei width, GC3Dsizei height, GC3Dint border,
4319                                                       GC3Denum format, GC3Denum type)
4320 {
4321     // We absolutely have to validate the format and type combination.
4322     // The texImage2D entry points taking HTMLImage, etc. will produce
4323     // temporary data based on this combination, so it must be legal.
4324     if (!validateTexFuncFormatAndType(format, type) || !validateTexFuncLevel(target, level))
4325         return false;
4326 
4327     if (width < 0 || height < 0) {
4328         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
4329         return false;
4330     }
4331 
4332     switch (target) {
4333     case GraphicsContext3D::TEXTURE_2D:
4334         if (width > m_maxTextureSize || height > m_maxTextureSize) {
4335             m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
4336             return false;
4337         }
4338         break;
4339     case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_X:
4340     case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_X:
4341     case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Y:
4342     case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Y:
4343     case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Z:
4344     case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Z:
4345         if (width != height || width > m_maxCubeMapTextureSize) {
4346             m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
4347             return false;
4348         }
4349         break;
4350     default:
4351         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
4352         return false;
4353     }
4354 
4355     if (format != internalformat) {
4356         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
4357         return false;
4358     }
4359 
4360     if (border) {
4361         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
4362         return false;
4363     }
4364 
4365     return true;
4366 }
4367 
validateTexFuncData(GC3Dsizei width,GC3Dsizei height,GC3Denum format,GC3Denum type,ArrayBufferView * pixels)4368 bool WebGLRenderingContext::validateTexFuncData(GC3Dsizei width, GC3Dsizei height,
4369                                                 GC3Denum format, GC3Denum type,
4370                                                 ArrayBufferView* pixels)
4371 {
4372     if (!pixels)
4373         return true;
4374 
4375     if (!validateTexFuncFormatAndType(format, type))
4376         return false;
4377 
4378     switch (type) {
4379     case GraphicsContext3D::UNSIGNED_BYTE:
4380         if (!pixels->isUnsignedByteArray()) {
4381             m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
4382             return false;
4383         }
4384         break;
4385     case GraphicsContext3D::UNSIGNED_SHORT_5_6_5:
4386     case GraphicsContext3D::UNSIGNED_SHORT_4_4_4_4:
4387     case GraphicsContext3D::UNSIGNED_SHORT_5_5_5_1:
4388         if (!pixels->isUnsignedShortArray()) {
4389             m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
4390             return false;
4391         }
4392         break;
4393     case GraphicsContext3D::FLOAT: // OES_texture_float
4394         if (!pixels->isFloatArray()) {
4395             m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
4396             return false;
4397         }
4398         break;
4399     default:
4400         ASSERT_NOT_REACHED();
4401     }
4402 
4403     unsigned int totalBytesRequired;
4404     GC3Denum error = m_context->computeImageSizeInBytes(format, type, width, height, m_unpackAlignment, &totalBytesRequired, 0);
4405     if (error != GraphicsContext3D::NO_ERROR) {
4406         m_context->synthesizeGLError(error);
4407         return false;
4408     }
4409     if (pixels->byteLength() < totalBytesRequired) {
4410         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
4411         return false;
4412     }
4413     return true;
4414 }
4415 
validateDrawMode(GC3Denum mode)4416 bool WebGLRenderingContext::validateDrawMode(GC3Denum mode)
4417 {
4418     switch (mode) {
4419     case GraphicsContext3D::POINTS:
4420     case GraphicsContext3D::LINE_STRIP:
4421     case GraphicsContext3D::LINE_LOOP:
4422     case GraphicsContext3D::LINES:
4423     case GraphicsContext3D::TRIANGLE_STRIP:
4424     case GraphicsContext3D::TRIANGLE_FAN:
4425     case GraphicsContext3D::TRIANGLES:
4426         return true;
4427     default:
4428         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
4429         return false;
4430     }
4431 }
4432 
validateStencilSettings()4433 bool WebGLRenderingContext::validateStencilSettings()
4434 {
4435     if (m_stencilMask != m_stencilMaskBack || m_stencilFuncRef != m_stencilFuncRefBack || m_stencilFuncMask != m_stencilFuncMaskBack) {
4436         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
4437         return false;
4438     }
4439     return true;
4440 }
4441 
validateStencilFunc(GC3Denum func)4442 bool WebGLRenderingContext::validateStencilFunc(GC3Denum func)
4443 {
4444     switch (func) {
4445     case GraphicsContext3D::NEVER:
4446     case GraphicsContext3D::LESS:
4447     case GraphicsContext3D::LEQUAL:
4448     case GraphicsContext3D::GREATER:
4449     case GraphicsContext3D::GEQUAL:
4450     case GraphicsContext3D::EQUAL:
4451     case GraphicsContext3D::NOTEQUAL:
4452     case GraphicsContext3D::ALWAYS:
4453         return true;
4454     default:
4455         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
4456         return false;
4457     }
4458 }
4459 
printWarningToConsole(const String & message)4460 void WebGLRenderingContext::printWarningToConsole(const String& message)
4461 {
4462     canvas()->document()->frame()->domWindow()->console()->addMessage(HTMLMessageSource, LogMessageType, WarningMessageLevel,
4463                                                                       message, 0, canvas()->document()->url().string());
4464 }
4465 
validateFramebufferFuncParameters(GC3Denum target,GC3Denum attachment)4466 bool WebGLRenderingContext::validateFramebufferFuncParameters(GC3Denum target, GC3Denum attachment)
4467 {
4468     if (target != GraphicsContext3D::FRAMEBUFFER) {
4469         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
4470         return false;
4471     }
4472     switch (attachment) {
4473     case GraphicsContext3D::COLOR_ATTACHMENT0:
4474     case GraphicsContext3D::DEPTH_ATTACHMENT:
4475     case GraphicsContext3D::STENCIL_ATTACHMENT:
4476     case GraphicsContext3D::DEPTH_STENCIL_ATTACHMENT:
4477         break;
4478     default:
4479         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
4480         return false;
4481     }
4482     return true;
4483 }
4484 
validateBlendEquation(GC3Denum mode)4485 bool WebGLRenderingContext::validateBlendEquation(GC3Denum mode)
4486 {
4487     switch (mode) {
4488     case GraphicsContext3D::FUNC_ADD:
4489     case GraphicsContext3D::FUNC_SUBTRACT:
4490     case GraphicsContext3D::FUNC_REVERSE_SUBTRACT:
4491         return true;
4492     default:
4493         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
4494         return false;
4495     }
4496 }
4497 
validateBlendFuncFactors(GC3Denum src,GC3Denum dst)4498 bool WebGLRenderingContext::validateBlendFuncFactors(GC3Denum src, GC3Denum dst)
4499 {
4500     if (((src == GraphicsContext3D::CONSTANT_COLOR || src == GraphicsContext3D::ONE_MINUS_CONSTANT_COLOR)
4501          && (dst == GraphicsContext3D::CONSTANT_ALPHA || dst == GraphicsContext3D::ONE_MINUS_CONSTANT_ALPHA))
4502         || ((dst == GraphicsContext3D::CONSTANT_COLOR || dst == GraphicsContext3D::ONE_MINUS_CONSTANT_COLOR)
4503             && (src == GraphicsContext3D::CONSTANT_ALPHA || src == GraphicsContext3D::ONE_MINUS_CONSTANT_ALPHA))) {
4504         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
4505         return false;
4506     }
4507     return true;
4508 }
4509 
validateCapability(GC3Denum cap)4510 bool WebGLRenderingContext::validateCapability(GC3Denum cap)
4511 {
4512     switch (cap) {
4513     case GraphicsContext3D::BLEND:
4514     case GraphicsContext3D::CULL_FACE:
4515     case GraphicsContext3D::DEPTH_TEST:
4516     case GraphicsContext3D::DITHER:
4517     case GraphicsContext3D::POLYGON_OFFSET_FILL:
4518     case GraphicsContext3D::SAMPLE_ALPHA_TO_COVERAGE:
4519     case GraphicsContext3D::SAMPLE_COVERAGE:
4520     case GraphicsContext3D::SCISSOR_TEST:
4521     case GraphicsContext3D::STENCIL_TEST:
4522         return true;
4523     default:
4524         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
4525         return false;
4526     }
4527 }
4528 
validateUniformParameters(const WebGLUniformLocation * location,Float32Array * v,GC3Dsizei requiredMinSize)4529 bool WebGLRenderingContext::validateUniformParameters(const WebGLUniformLocation* location, Float32Array* v, GC3Dsizei requiredMinSize)
4530 {
4531     if (!v) {
4532         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
4533         return false;
4534     }
4535     return validateUniformMatrixParameters(location, false, v->data(), v->length(), requiredMinSize);
4536 }
4537 
validateUniformParameters(const WebGLUniformLocation * location,Int32Array * v,GC3Dsizei requiredMinSize)4538 bool WebGLRenderingContext::validateUniformParameters(const WebGLUniformLocation* location, Int32Array* v, GC3Dsizei requiredMinSize)
4539 {
4540     if (!v) {
4541         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
4542         return false;
4543     }
4544     return validateUniformMatrixParameters(location, false, v->data(), v->length(), requiredMinSize);
4545 }
4546 
validateUniformParameters(const WebGLUniformLocation * location,void * v,GC3Dsizei size,GC3Dsizei requiredMinSize)4547 bool WebGLRenderingContext::validateUniformParameters(const WebGLUniformLocation* location, void* v, GC3Dsizei size, GC3Dsizei requiredMinSize)
4548 {
4549     return validateUniformMatrixParameters(location, false, v, size, requiredMinSize);
4550 }
4551 
validateUniformMatrixParameters(const WebGLUniformLocation * location,GC3Dboolean transpose,Float32Array * v,GC3Dsizei requiredMinSize)4552 bool WebGLRenderingContext::validateUniformMatrixParameters(const WebGLUniformLocation* location, GC3Dboolean transpose, Float32Array* v, GC3Dsizei requiredMinSize)
4553 {
4554     if (!v) {
4555         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
4556         return false;
4557     }
4558     return validateUniformMatrixParameters(location, transpose, v->data(), v->length(), requiredMinSize);
4559 }
4560 
validateUniformMatrixParameters(const WebGLUniformLocation * location,GC3Dboolean transpose,void * v,GC3Dsizei size,GC3Dsizei requiredMinSize)4561 bool WebGLRenderingContext::validateUniformMatrixParameters(const WebGLUniformLocation* location, GC3Dboolean transpose, void* v, GC3Dsizei size, GC3Dsizei requiredMinSize)
4562 {
4563     if (!location)
4564         return false;
4565     if (location->program() != m_currentProgram) {
4566         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
4567         return false;
4568     }
4569     if (!v) {
4570         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
4571         return false;
4572     }
4573     if (transpose) {
4574         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
4575         return false;
4576     }
4577     if (size < requiredMinSize || (size % requiredMinSize)) {
4578         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
4579         return false;
4580     }
4581     return true;
4582 }
4583 
validateBufferDataParameters(GC3Denum target,GC3Denum usage)4584 WebGLBuffer* WebGLRenderingContext::validateBufferDataParameters(GC3Denum target, GC3Denum usage)
4585 {
4586     WebGLBuffer* buffer = 0;
4587     switch (target) {
4588     case GraphicsContext3D::ELEMENT_ARRAY_BUFFER:
4589         buffer = m_boundVertexArrayObject->getElementArrayBuffer().get();
4590         break;
4591     case GraphicsContext3D::ARRAY_BUFFER:
4592         buffer = m_boundArrayBuffer.get();
4593         break;
4594     default:
4595         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
4596         return 0;
4597     }
4598     if (!buffer) {
4599         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
4600         return 0;
4601     }
4602     switch (usage) {
4603     case GraphicsContext3D::STREAM_DRAW:
4604     case GraphicsContext3D::STATIC_DRAW:
4605     case GraphicsContext3D::DYNAMIC_DRAW:
4606         return buffer;
4607     }
4608     m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
4609     return 0;
4610 }
4611 
validateHTMLImageElement(HTMLImageElement * image)4612 bool WebGLRenderingContext::validateHTMLImageElement(HTMLImageElement* image)
4613 {
4614     if (!image || !image->cachedImage()) {
4615         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
4616         return false;
4617     }
4618     const KURL& url = image->cachedImage()->response().url();
4619     if (url.isNull() || url.isEmpty() || !url.isValid()) {
4620         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
4621         return false;
4622     }
4623     return true;
4624 }
4625 
vertexAttribfImpl(GC3Duint index,GC3Dsizei expectedSize,GC3Dfloat v0,GC3Dfloat v1,GC3Dfloat v2,GC3Dfloat v3)4626 void WebGLRenderingContext::vertexAttribfImpl(GC3Duint index, GC3Dsizei expectedSize, GC3Dfloat v0, GC3Dfloat v1, GC3Dfloat v2, GC3Dfloat v3)
4627 {
4628     if (isContextLost())
4629         return;
4630     if (index >= m_maxVertexAttribs) {
4631         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
4632         return;
4633     }
4634     // In GL, we skip setting vertexAttrib0 values.
4635     if (index || isGLES2Compliant()) {
4636         switch (expectedSize) {
4637         case 1:
4638             m_context->vertexAttrib1f(index, v0);
4639             break;
4640         case 2:
4641             m_context->vertexAttrib2f(index, v0, v1);
4642             break;
4643         case 3:
4644             m_context->vertexAttrib3f(index, v0, v1, v2);
4645             break;
4646         case 4:
4647             m_context->vertexAttrib4f(index, v0, v1, v2, v3);
4648             break;
4649         }
4650         cleanupAfterGraphicsCall(false);
4651     }
4652     VertexAttribValue& attribValue = m_vertexAttribValue[index];
4653     attribValue.value[0] = v0;
4654     attribValue.value[1] = v1;
4655     attribValue.value[2] = v2;
4656     attribValue.value[3] = v3;
4657 }
4658 
vertexAttribfvImpl(GC3Duint index,Float32Array * v,GC3Dsizei expectedSize)4659 void WebGLRenderingContext::vertexAttribfvImpl(GC3Duint index, Float32Array* v, GC3Dsizei expectedSize)
4660 {
4661     if (isContextLost())
4662         return;
4663     if (!v) {
4664         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
4665         return;
4666     }
4667     vertexAttribfvImpl(index, v->data(), v->length(), expectedSize);
4668 }
4669 
vertexAttribfvImpl(GC3Duint index,GC3Dfloat * v,GC3Dsizei size,GC3Dsizei expectedSize)4670 void WebGLRenderingContext::vertexAttribfvImpl(GC3Duint index, GC3Dfloat* v, GC3Dsizei size, GC3Dsizei expectedSize)
4671 {
4672     if (isContextLost())
4673         return;
4674     if (!v) {
4675         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
4676         return;
4677     }
4678     if (size < expectedSize) {
4679         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
4680         return;
4681     }
4682     if (index >= m_maxVertexAttribs) {
4683         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
4684         return;
4685     }
4686     // In GL, we skip setting vertexAttrib0 values.
4687     if (index || isGLES2Compliant()) {
4688         switch (expectedSize) {
4689         case 1:
4690             m_context->vertexAttrib1fv(index, v);
4691             break;
4692         case 2:
4693             m_context->vertexAttrib2fv(index, v);
4694             break;
4695         case 3:
4696             m_context->vertexAttrib3fv(index, v);
4697             break;
4698         case 4:
4699             m_context->vertexAttrib4fv(index, v);
4700             break;
4701         }
4702         cleanupAfterGraphicsCall(false);
4703     }
4704     VertexAttribValue& attribValue = m_vertexAttribValue[index];
4705     attribValue.initValue();
4706     for (int ii = 0; ii < expectedSize; ++ii)
4707         attribValue.value[ii] = v[ii];
4708 }
4709 
initVertexAttrib0()4710 void WebGLRenderingContext::initVertexAttrib0()
4711 {
4712     WebGLVertexArrayObjectOES::VertexAttribState& state = m_boundVertexArrayObject->getVertexAttribState(0);
4713 
4714     m_vertexAttrib0Buffer = createBuffer();
4715     m_context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, m_vertexAttrib0Buffer->object());
4716     m_context->bufferData(GraphicsContext3D::ARRAY_BUFFER, 0, GraphicsContext3D::DYNAMIC_DRAW);
4717     m_context->vertexAttribPointer(0, 4, GraphicsContext3D::FLOAT, false, 0, 0);
4718     state.bufferBinding = m_vertexAttrib0Buffer;
4719     m_context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, 0);
4720     m_context->enableVertexAttribArray(0);
4721     m_vertexAttrib0BufferSize = 0;
4722     m_vertexAttrib0BufferValue[0] = 0.0f;
4723     m_vertexAttrib0BufferValue[1] = 0.0f;
4724     m_vertexAttrib0BufferValue[2] = 0.0f;
4725     m_vertexAttrib0BufferValue[3] = 1.0f;
4726     m_forceAttrib0BufferRefill = false;
4727     m_vertexAttrib0UsedBefore = false;
4728 }
4729 
simulateVertexAttrib0(GC3Dsizei numVertex)4730 bool WebGLRenderingContext::simulateVertexAttrib0(GC3Dsizei numVertex)
4731 {
4732     const WebGLVertexArrayObjectOES::VertexAttribState& state = m_boundVertexArrayObject->getVertexAttribState(0);
4733     const VertexAttribValue& attribValue = m_vertexAttribValue[0];
4734     if (!m_currentProgram)
4735         return false;
4736     bool usingVertexAttrib0 = m_currentProgram->isUsingVertexAttrib0();
4737     if (usingVertexAttrib0)
4738         m_vertexAttrib0UsedBefore = true;
4739     if (state.enabled && usingVertexAttrib0)
4740         return false;
4741     if (!usingVertexAttrib0 && !m_vertexAttrib0UsedBefore)
4742         return false;
4743     m_vertexAttrib0UsedBefore = true;
4744     m_context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, m_vertexAttrib0Buffer->object());
4745     GC3Dsizeiptr bufferDataSize = (numVertex + 1) * 4 * sizeof(GC3Dfloat);
4746     if (bufferDataSize > m_vertexAttrib0BufferSize) {
4747         m_context->bufferData(GraphicsContext3D::ARRAY_BUFFER, bufferDataSize, 0, GraphicsContext3D::DYNAMIC_DRAW);
4748         m_vertexAttrib0BufferSize = bufferDataSize;
4749         m_forceAttrib0BufferRefill = true;
4750     }
4751     if (usingVertexAttrib0
4752         && (m_forceAttrib0BufferRefill
4753             || attribValue.value[0] != m_vertexAttrib0BufferValue[0]
4754             || attribValue.value[1] != m_vertexAttrib0BufferValue[1]
4755             || attribValue.value[2] != m_vertexAttrib0BufferValue[2]
4756             || attribValue.value[3] != m_vertexAttrib0BufferValue[3])) {
4757         OwnArrayPtr<GC3Dfloat> bufferData = adoptArrayPtr(new GC3Dfloat[(numVertex + 1) * 4]);
4758         for (GC3Dsizei ii = 0; ii < numVertex + 1; ++ii) {
4759             bufferData[ii * 4] = attribValue.value[0];
4760             bufferData[ii * 4 + 1] = attribValue.value[1];
4761             bufferData[ii * 4 + 2] = attribValue.value[2];
4762             bufferData[ii * 4 + 3] = attribValue.value[3];
4763         }
4764         m_vertexAttrib0BufferValue[0] = attribValue.value[0];
4765         m_vertexAttrib0BufferValue[1] = attribValue.value[1];
4766         m_vertexAttrib0BufferValue[2] = attribValue.value[2];
4767         m_vertexAttrib0BufferValue[3] = attribValue.value[3];
4768         m_forceAttrib0BufferRefill = false;
4769         m_context->bufferSubData(GraphicsContext3D::ARRAY_BUFFER, 0, bufferDataSize, bufferData.get());
4770     }
4771     m_context->vertexAttribPointer(0, 4, GraphicsContext3D::FLOAT, 0, 0, 0);
4772     return true;
4773 }
4774 
restoreStatesAfterVertexAttrib0Simulation()4775 void WebGLRenderingContext::restoreStatesAfterVertexAttrib0Simulation()
4776 {
4777     const WebGLVertexArrayObjectOES::VertexAttribState& state = m_boundVertexArrayObject->getVertexAttribState(0);
4778     if (state.bufferBinding != m_vertexAttrib0Buffer) {
4779         m_context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, objectOrZero(state.bufferBinding.get()));
4780         m_context->vertexAttribPointer(0, state.size, state.type, state.normalized, state.originalStride, state.offset);
4781     }
4782     m_context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, objectOrZero(m_boundArrayBuffer.get()));
4783 }
4784 
getNumberOfExtensions()4785 int WebGLRenderingContext::getNumberOfExtensions()
4786 {
4787     return (m_oesVertexArrayObject ? 1 : 0) + (m_oesStandardDerivatives ? 1 : 0) + (m_webkitLoseContext ? 1 : 0) + (m_oesTextureFloat ? 1 : 0);
4788 }
4789 
getExtensionNumber(int i)4790 WebGLExtension* WebGLRenderingContext::getExtensionNumber(int i)
4791 {
4792     if (m_oesVertexArrayObject) {
4793         if (!i)
4794             return m_oesVertexArrayObject.get();
4795         --i;
4796     }
4797     if (m_oesStandardDerivatives) {
4798         if (!i)
4799             return m_oesStandardDerivatives.get();
4800         --i;
4801     }
4802     if (m_webkitLoseContext) {
4803         if (!i)
4804             return m_webkitLoseContext.get();
4805         --i;
4806     }
4807     if (m_oesTextureFloat) {
4808         if (!i)
4809             return m_oesTextureFloat.get();
4810         --i;
4811     }
4812     // Similar tests for other extensions would go here.
4813     return 0;
4814 }
4815 
LRUImageBufferCache(int capacity)4816 WebGLRenderingContext::LRUImageBufferCache::LRUImageBufferCache(int capacity)
4817     : m_buffers(adoptArrayPtr(new OwnPtr<ImageBuffer>[capacity]))
4818     , m_capacity(capacity)
4819 {
4820 }
4821 
imageBuffer(const IntSize & size)4822 ImageBuffer* WebGLRenderingContext::LRUImageBufferCache::imageBuffer(const IntSize& size)
4823 {
4824     int i;
4825     for (i = 0; i < m_capacity; ++i) {
4826         ImageBuffer* buf = m_buffers[i].get();
4827         if (!buf)
4828             break;
4829         if (buf->size() != size)
4830             continue;
4831         bubbleToFront(i);
4832         return buf;
4833     }
4834 
4835     OwnPtr<ImageBuffer> temp = ImageBuffer::create(size);
4836     if (!temp)
4837         return 0;
4838     i = std::min(m_capacity - 1, i);
4839     m_buffers[i] = temp.release();
4840 
4841     ImageBuffer* buf = m_buffers[i].get();
4842     bubbleToFront(i);
4843     return buf;
4844 }
4845 
bubbleToFront(int idx)4846 void WebGLRenderingContext::LRUImageBufferCache::bubbleToFront(int idx)
4847 {
4848     for (int i = idx; i > 0; --i)
4849         m_buffers[i].swap(m_buffers[i-1]);
4850 }
4851 
4852 } // namespace WebCore
4853 
4854 #endif // ENABLE(WEBGL)
4855