2 * Copyright (C) 2009 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
30 #include "WebGLRenderingContext.h"
32 #include "CachedImage.h"
33 #include "CanvasPixelArray.h"
34 #include "CheckedInt.h"
35 #include "WebKitLoseContext.h"
37 #include "DOMWindow.h"
38 #include "Extensions3D.h"
40 #include "FrameView.h"
41 #include "HTMLCanvasElement.h"
42 #include "HTMLImageElement.h"
43 #include "HTMLVideoElement.h"
44 #include "ImageBuffer.h"
45 #include "ImageData.h"
47 #include "NotImplemented.h"
48 #include "OESStandardDerivatives.h"
49 #include "OESTextureFloat.h"
50 #include "OESVertexArrayObject.h"
52 #include "RenderBox.h"
53 #include "RenderLayer.h"
55 #include "Uint16Array.h"
56 #include "WebGLActiveInfo.h"
57 #include "WebGLBuffer.h"
58 #include "WebGLContextAttributes.h"
59 #include "WebGLContextEvent.h"
60 #include "WebGLFramebuffer.h"
61 #include "WebGLProgram.h"
62 #include "WebGLRenderbuffer.h"
63 #include "WebGLShader.h"
64 #include "WebGLTexture.h"
65 #include "WebGLUniformLocation.h"
67 #include <wtf/ByteArray.h>
68 #include <wtf/OwnArrayPtr.h>
69 #include <wtf/PassOwnArrayPtr.h>
70 #include <wtf/text/StringBuilder.h>
78 const double secondsBetweenRestoreAttempts = 1.0;
82 Platform3DObject objectOrZero(WebGLObject* object)
84 return object ? object->object() : 0;
87 void clip1D(GC3Dint start, GC3Dsizei range, GC3Dsizei sourceRange, GC3Dint* clippedStart, GC3Dsizei* clippedRange)
89 ASSERT(clippedStart && clippedRange);
94 GC3Dint end = start + range;
95 if (end > sourceRange)
96 range -= end - sourceRange;
97 *clippedStart = start;
98 *clippedRange = range;
101 // Returns false if no clipping is necessary, i.e., x, y, width, height stay the same.
102 bool clip2D(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height,
103 GC3Dsizei sourceWidth, GC3Dsizei sourceHeight,
104 GC3Dint* clippedX, GC3Dint* clippedY, GC3Dsizei* clippedWidth, GC3Dsizei*clippedHeight)
106 ASSERT(clippedX && clippedY && clippedWidth && clippedHeight);
107 clip1D(x, width, sourceWidth, clippedX, clippedWidth);
108 clip1D(y, height, sourceHeight, clippedY, clippedHeight);
109 return (*clippedX != x || *clippedY != y || *clippedWidth != width || *clippedHeight != height);
112 GC3Dint clamp(GC3Dint value, GC3Dint min, GC3Dint max)
121 // Return true if a character belongs to the ASCII subset as defined in
122 // GLSL ES 1.0 spec section 3.1.
123 bool validateCharacter(unsigned char c)
125 // Printing characters are valid except " $ ` @ \ ' DEL.
126 if (c >= 32 && c <= 126
127 && c != '"' && c != '$' && c != '`' && c != '@' && c != '\\' && c != '\'')
129 // Horizontal tab, line feed, vertical tab, form feed, carriage return
131 if (c >= 9 && c <= 13)
136 // Strips comments from shader text. This allows non-ASCII characters
137 // to be used in comments without potentially breaking OpenGL
138 // implementations not expecting characters outside the GLSL ES set.
139 class StripComments {
141 StripComments(const String& str)
142 : m_parseState(BeginningOfLine)
143 , m_sourceString(str)
144 , m_length(str.length())
152 return m_builder.toString();
156 bool hasMoreCharacters()
158 return (m_position < m_length);
163 while (hasMoreCharacters()) {
165 // process() might advance the position.
166 if (hasMoreCharacters())
173 bool peek(UChar& character)
175 if (m_position + 1 >= m_length)
177 character = m_sourceString[m_position + 1];
183 ASSERT(m_position < m_length);
184 return m_sourceString[m_position];
192 bool isNewline(UChar character)
194 // Don't attempt to canonicalize newline related characters.
195 return (character == '\n' || character == '\r');
198 void emit(UChar character)
200 m_builder.append(character);
204 // Have not seen an ASCII non-whitespace character yet on
205 // this line. Possible that we might see a preprocessor
209 // Have seen at least one ASCII non-whitespace character
213 // Handling a preprocessor directive. Passes through all
214 // characters up to the end of the line. Disables comment
216 InPreprocessorDirective,
218 // Handling a single-line comment. The comment text is
219 // replaced with a single space.
222 // Handling a multi-line comment. Newlines are passed
223 // through to preserve line numbers.
227 ParseState m_parseState;
228 String m_sourceString;
231 StringBuilder m_builder;
234 void StripComments::process(UChar c)
237 // No matter what state we are in, pass through newlines
238 // so we preserve line numbers.
241 if (m_parseState != InMultiLineComment)
242 m_parseState = BeginningOfLine;
248 switch (m_parseState) {
249 case BeginningOfLine:
250 if (WTF::isASCIISpace(c)) {
256 m_parseState = InPreprocessorDirective;
261 // Transition to normal state and re-handle character.
262 m_parseState = MiddleOfLine;
267 if (c == '/' && peek(temp)) {
269 m_parseState = InSingleLineComment;
276 m_parseState = InMultiLineComment;
277 // Emit the comment start in case the user has
278 // an unclosed comment and we want to later
290 case InPreprocessorDirective:
291 // No matter what the character is, just pass it
292 // through. Do not parse comments in this state. This
293 // might not be the right thing to do long term, but it
294 // should handle the #error preprocessor directive.
298 case InSingleLineComment:
299 // The newline code at the top of this function takes care
300 // of resetting our state when we get out of the
301 // single-line comment. Swallow all other characters.
304 case InMultiLineComment:
305 if (c == '*' && peek(temp) && temp == '/') {
308 m_parseState = MiddleOfLine;
313 // Swallow all other characters. Unclear whether we may
314 // want or need to just emit a space per character to try
315 // to preserve column numbers for debugging purposes.
319 } // namespace anonymous
321 class WebGLStateRestorer {
323 WebGLStateRestorer(WebGLRenderingContext* context,
330 ~WebGLStateRestorer()
332 m_context->cleanupAfterGraphicsCall(m_changed);
336 WebGLRenderingContext* m_context;
340 void WebGLRenderingContext::WebGLRenderingContextRestoreTimer::fired()
342 m_context->maybeRestoreContext(RealLostContext);
345 class WebGLRenderingContextLostCallback : public GraphicsContext3D::ContextLostCallback {
347 explicit WebGLRenderingContextLostCallback(WebGLRenderingContext* cb) : m_context(cb) { }
348 virtual void onContextLost() { m_context->forceLostContext(WebGLRenderingContext::RealLostContext); }
349 virtual ~WebGLRenderingContextLostCallback() {}
351 WebGLRenderingContext* m_context;
354 PassOwnPtr<WebGLRenderingContext> WebGLRenderingContext::create(HTMLCanvasElement* canvas, WebGLContextAttributes* attrs)
356 HostWindow* hostWindow = canvas->document()->view()->root()->hostWindow();
357 GraphicsContext3D::Attributes attributes = attrs ? attrs->attributes() : GraphicsContext3D::Attributes();
359 if (attributes.antialias) {
360 Page* p = canvas->document()->page();
361 if (p && !p->settings()->openGLMultisamplingEnabled())
362 attributes.antialias = false;
365 attributes.noExtensions = true;
366 attributes.shareResources = false;
368 RefPtr<GraphicsContext3D> context(GraphicsContext3D::create(attributes, hostWindow));
371 canvas->dispatchEvent(WebGLContextEvent::create(eventNames().webglcontextcreationerrorEvent, false, true, "Could not create a WebGL context."));
375 return adoptPtr(new WebGLRenderingContext(canvas, context, attributes));
378 WebGLRenderingContext::WebGLRenderingContext(HTMLCanvasElement* passedCanvas, PassRefPtr<GraphicsContext3D> context,
379 GraphicsContext3D::Attributes attributes)
380 : CanvasRenderingContext(passedCanvas)
382 , m_restoreAllowed(false)
383 , m_restoreTimer(this)
385 , m_contextLost(false)
386 , m_attributes(attributes)
390 initializeNewContext();
393 void WebGLRenderingContext::initializeNewContext()
395 ASSERT(!m_contextLost);
396 m_needsUpdate = true;
397 m_markedCanvasDirty = false;
398 m_activeTextureUnit = 0;
400 m_unpackAlignment = 4;
401 m_unpackFlipY = false;
402 m_unpackPremultiplyAlpha = false;
403 m_unpackColorspaceConversion = GraphicsContext3D::BROWSER_DEFAULT_WEBGL;
404 m_boundArrayBuffer = 0;
405 m_currentProgram = 0;
406 m_framebufferBinding = 0;
407 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;
417 m_clearColor[0] = m_clearColor[1] = m_clearColor[2] = m_clearColor[3] = 0;
418 m_scissorEnabled = false;
421 m_colorMask[0] = m_colorMask[1] = m_colorMask[2] = m_colorMask[3] = true;
423 GC3Dint numCombinedTextureImageUnits = 0;
424 m_context->getIntegerv(GraphicsContext3D::MAX_COMBINED_TEXTURE_IMAGE_UNITS, &numCombinedTextureImageUnits);
425 m_textureUnits.clear();
426 m_textureUnits.resize(numCombinedTextureImageUnits);
428 GC3Dint numVertexAttribs = 0;
429 m_context->getIntegerv(GraphicsContext3D::MAX_VERTEX_ATTRIBS, &numVertexAttribs);
430 m_maxVertexAttribs = numVertexAttribs;
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 m_maxRenderbufferSize = 0;
439 m_context->getIntegerv(GraphicsContext3D::MAX_RENDERBUFFER_SIZE, &m_maxRenderbufferSize);
440 m_maxViewportDims[0] = m_maxViewportDims[1] = 0;
441 m_context->getIntegerv(GraphicsContext3D::MAX_VIEWPORT_DIMS, m_maxViewportDims);
443 m_defaultVertexArrayObject = WebGLVertexArrayObjectOES::create(this, WebGLVertexArrayObjectOES::VaoTypeDefault);
444 addObject(m_defaultVertexArrayObject.get());
445 m_boundVertexArrayObject = m_defaultVertexArrayObject;
447 m_vertexAttribValue.resize(m_maxVertexAttribs);
449 if (!isGLES2NPOTStrict())
450 createFallbackBlackTextures1x1();
451 if (!isGLES2Compliant())
454 m_context->reshape(canvas()->width(), canvas()->height());
455 m_context->viewport(0, 0, canvas()->width(), canvas()->height());
457 m_context->setContextLostCallback(adoptPtr(new WebGLRenderingContextLostCallback(this)));
460 void WebGLRenderingContext::setupFlags()
464 m_isGLES2Compliant = m_context->isGLES2Compliant();
465 m_isErrorGeneratedOnOutOfBoundsAccesses = m_context->getExtensions()->isEnabled("GL_CHROMIUM_strict_attribs");
466 m_isResourceSafe = m_context->getExtensions()->isEnabled("GL_CHROMIUM_resource_safe");
467 if (m_isGLES2Compliant) {
468 m_isGLES2NPOTStrict = !m_context->getExtensions()->isEnabled("GL_OES_texture_npot");
469 m_isDepthStencilSupported = m_context->getExtensions()->isEnabled("GL_OES_packed_depth_stencil");
471 m_isGLES2NPOTStrict = !m_context->getExtensions()->isEnabled("GL_ARB_texture_non_power_of_two");
472 m_isDepthStencilSupported = m_context->getExtensions()->isEnabled("GL_EXT_packed_depth_stencil");
476 WebGLRenderingContext::~WebGLRenderingContext()
478 detachAndRemoveAllObjects();
479 m_context->setContextLostCallback(nullptr);
482 void WebGLRenderingContext::markContextChanged()
484 if (m_framebufferBinding)
486 m_context->markContextChanged();
487 m_layerCleared = false;
488 #if USE(ACCELERATED_COMPOSITING)
489 RenderBox* renderBox = canvas()->renderBox();
490 if (renderBox && renderBox->hasLayer() && renderBox->layer()->hasAcceleratedCompositing())
491 renderBox->layer()->contentChanged(RenderLayer::CanvasChanged);
494 if (!m_markedCanvasDirty)
495 canvas()->didDraw(FloatRect(0, 0, canvas()->width(), canvas()->height()));
496 #if USE(ACCELERATED_COMPOSITING)
499 m_markedCanvasDirty = true;
502 bool WebGLRenderingContext::clearIfComposited(GC3Dbitfield mask)
507 if (!m_context->layerComposited() || m_layerCleared
508 || m_attributes.preserveDrawingBuffer || (mask && m_framebufferBinding))
511 RefPtr<WebGLContextAttributes> contextAttributes = getContextAttributes();
513 // Determine if it's possible to combine the clear the user asked for and this clear.
514 bool combinedClear = mask && !m_scissorEnabled;
516 if (m_framebufferBinding)
517 m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, 0);
518 m_context->disable(GraphicsContext3D::SCISSOR_TEST);
519 if (combinedClear && (mask & GraphicsContext3D::COLOR_BUFFER_BIT))
520 m_context->clearColor(m_colorMask[0] ? m_clearColor[0] : 0,
521 m_colorMask[1] ? m_clearColor[1] : 0,
522 m_colorMask[2] ? m_clearColor[2] : 0,
523 m_colorMask[3] ? m_clearColor[3] : 0);
525 m_context->clearColor(0, 0, 0, 0);
526 m_context->colorMask(true, true, true, true);
527 GC3Dbitfield clearMask = GraphicsContext3D::COLOR_BUFFER_BIT;
528 if (contextAttributes->depth()) {
529 if (!combinedClear || !m_depthMask || !(mask & GraphicsContext3D::DEPTH_BUFFER_BIT))
530 m_context->clearDepth(1.0f);
531 clearMask |= GraphicsContext3D::DEPTH_BUFFER_BIT;
532 m_context->depthMask(true);
534 if (contextAttributes->stencil()) {
535 if (combinedClear && (mask & GraphicsContext3D::STENCIL_BUFFER_BIT))
536 m_context->clearStencil(m_clearStencil & m_stencilMask);
538 m_context->clearStencil(0);
539 clearMask |= GraphicsContext3D::STENCIL_BUFFER_BIT;
540 m_context->stencilMaskSeparate(GraphicsContext3D::FRONT, 0xFFFFFFFF);
542 m_context->clear(clearMask);
544 // Restore the state that the context set.
545 if (m_scissorEnabled)
546 m_context->enable(GraphicsContext3D::SCISSOR_TEST);
547 m_context->clearColor(m_clearColor[0], m_clearColor[1],
548 m_clearColor[2], m_clearColor[3]);
549 m_context->colorMask(m_colorMask[0], m_colorMask[1],
550 m_colorMask[2], m_colorMask[3]);
551 m_context->clearDepth(m_clearDepth);
552 m_context->clearStencil(m_clearStencil);
553 m_context->stencilMaskSeparate(GraphicsContext3D::FRONT, m_stencilMask);
554 m_context->depthMask(m_depthMask);
555 if (m_framebufferBinding)
556 m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, objectOrZero(m_framebufferBinding.get()));
557 m_layerCleared = true;
559 return combinedClear;
562 void WebGLRenderingContext::markLayerComposited()
564 m_context->markLayerComposited();
567 void WebGLRenderingContext::paintRenderingResultsToCanvas()
569 // Until the canvas is written to by the application, the clear that
570 // happened after it was composited should be ignored by the compositor.
571 if (m_context->layerComposited() && !m_attributes.preserveDrawingBuffer) {
572 m_context->paintCompositedResultsToCanvas(this);
573 canvas()->makePresentationCopy();
575 canvas()->clearPresentationCopy();
577 if (!m_markedCanvasDirty && !m_layerCleared)
579 canvas()->clearCopiedImage();
580 m_markedCanvasDirty = false;
581 m_context->paintRenderingResultsToCanvas(this);
584 PassRefPtr<ImageData> WebGLRenderingContext::paintRenderingResultsToImageData()
587 return m_context->paintRenderingResultsToImageData();
590 bool WebGLRenderingContext::paintsIntoCanvasBuffer() const
592 return m_context->paintsIntoCanvasBuffer();
595 void WebGLRenderingContext::reshape(int width, int height)
597 // This is an approximation because at WebGLRenderingContext level we don't
598 // know if the underlying FBO uses textures or renderbuffers.
599 GC3Dint maxSize = std::min(m_maxTextureSize, m_maxRenderbufferSize);
600 // Limit drawing buffer size to 4k to avoid memory exhaustion.
601 const int sizeUpperLimit = 4096;
602 maxSize = std::min(maxSize, sizeUpperLimit);
603 GC3Dint maxWidth = std::min(maxSize, m_maxViewportDims[0]);
604 GC3Dint maxHeight = std::min(maxSize, m_maxViewportDims[1]);
605 width = clamp(width, 1, maxWidth);
606 height = clamp(height, 1, maxHeight);
609 #if USE(ACCELERATED_COMPOSITING)
610 RenderBox* renderBox = canvas()->renderBox();
611 if (renderBox && renderBox->hasLayer())
612 renderBox->layer()->contentChanged(RenderLayer::CanvasChanged);
614 m_needsUpdate = false;
617 // We don't have to mark the canvas as dirty, since the newly created image buffer will also start off
618 // clear (and this matches what reshape will do).
619 m_context->reshape(width, height);
622 int WebGLRenderingContext::drawingBufferWidth() const
624 return m_context->getInternalFramebufferSize().width();
627 int WebGLRenderingContext::drawingBufferHeight() const
629 return m_context->getInternalFramebufferSize().height();
632 unsigned int WebGLRenderingContext::sizeInBytes(GC3Denum type)
635 case GraphicsContext3D::BYTE:
636 return sizeof(GC3Dbyte);
637 case GraphicsContext3D::UNSIGNED_BYTE:
638 return sizeof(GC3Dubyte);
639 case GraphicsContext3D::SHORT:
640 return sizeof(GC3Dshort);
641 case GraphicsContext3D::UNSIGNED_SHORT:
642 return sizeof(GC3Dushort);
643 case GraphicsContext3D::INT:
644 return sizeof(GC3Dint);
645 case GraphicsContext3D::UNSIGNED_INT:
646 return sizeof(GC3Duint);
647 case GraphicsContext3D::FLOAT:
648 return sizeof(GC3Dfloat);
650 ASSERT_NOT_REACHED();
654 void WebGLRenderingContext::activeTexture(GC3Denum texture, ExceptionCode& ec)
659 if (texture - GraphicsContext3D::TEXTURE0 >= m_textureUnits.size()) {
660 m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
663 m_activeTextureUnit = texture - GraphicsContext3D::TEXTURE0;
664 m_context->activeTexture(texture);
665 cleanupAfterGraphicsCall(false);
668 void WebGLRenderingContext::attachShader(WebGLProgram* program, WebGLShader* shader, ExceptionCode& ec)
671 if (isContextLost() || !validateWebGLObject(program) || !validateWebGLObject(shader))
673 if (!program->attachShader(shader)) {
674 m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
677 m_context->attachShader(objectOrZero(program), objectOrZero(shader));
678 shader->onAttached();
679 cleanupAfterGraphicsCall(false);
682 void WebGLRenderingContext::bindAttribLocation(WebGLProgram* program, GC3Duint index, const String& name, ExceptionCode& ec)
685 if (isContextLost() || !validateWebGLObject(program))
687 if (!validateString(name))
689 m_context->bindAttribLocation(objectOrZero(program), index, name);
690 cleanupAfterGraphicsCall(false);
693 bool WebGLRenderingContext::checkObjectToBeBound(WebGLObject* object, bool& deleted)
699 if (object->context() != this) {
700 m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
703 deleted = !object->object();
708 void WebGLRenderingContext::bindBuffer(GC3Denum target, WebGLBuffer* buffer, ExceptionCode& ec)
712 if (!checkObjectToBeBound(buffer, deleted))
716 if (buffer && buffer->getTarget() && buffer->getTarget() != target) {
717 m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
720 if (target == GraphicsContext3D::ARRAY_BUFFER)
721 m_boundArrayBuffer = buffer;
722 else if (target == GraphicsContext3D::ELEMENT_ARRAY_BUFFER)
723 m_boundVertexArrayObject->setElementArrayBuffer(buffer);
725 m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
729 m_context->bindBuffer(target, objectOrZero(buffer));
731 buffer->setTarget(target);
732 cleanupAfterGraphicsCall(false);
735 void WebGLRenderingContext::bindFramebuffer(GC3Denum target, WebGLFramebuffer* buffer, ExceptionCode& ec)
739 if (!checkObjectToBeBound(buffer, deleted))
743 if (target != GraphicsContext3D::FRAMEBUFFER) {
744 m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
747 m_framebufferBinding = buffer;
748 m_context->bindFramebuffer(target, objectOrZero(buffer));
750 buffer->setHasEverBeenBound();
751 cleanupAfterGraphicsCall(false);
754 void WebGLRenderingContext::bindRenderbuffer(GC3Denum target, WebGLRenderbuffer* renderBuffer, ExceptionCode& ec)
758 if (!checkObjectToBeBound(renderBuffer, deleted))
762 if (target != GraphicsContext3D::RENDERBUFFER) {
763 m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
766 m_renderbufferBinding = renderBuffer;
767 m_context->bindRenderbuffer(target, objectOrZero(renderBuffer));
769 renderBuffer->setHasEverBeenBound();
770 cleanupAfterGraphicsCall(false);
773 void WebGLRenderingContext::bindTexture(GC3Denum target, WebGLTexture* texture, ExceptionCode& ec)
777 if (!checkObjectToBeBound(texture, deleted))
781 if (texture && texture->getTarget() && texture->getTarget() != target) {
782 m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
785 GC3Dint maxLevel = 0;
786 if (target == GraphicsContext3D::TEXTURE_2D) {
787 m_textureUnits[m_activeTextureUnit].m_texture2DBinding = texture;
788 maxLevel = m_maxTextureLevel;
789 } else if (target == GraphicsContext3D::TEXTURE_CUBE_MAP) {
790 m_textureUnits[m_activeTextureUnit].m_textureCubeMapBinding = texture;
791 maxLevel = m_maxCubeMapTextureLevel;
793 m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
796 m_context->bindTexture(target, objectOrZero(texture));
798 texture->setTarget(target, maxLevel);
800 // Note: previously we used to automatically set the TEXTURE_WRAP_R
801 // repeat mode to CLAMP_TO_EDGE for cube map textures, because OpenGL
802 // ES 2.0 doesn't expose this flag (a bug in the specification) and
803 // otherwise the application has no control over the seams in this
804 // dimension. However, it appears that supporting this properly on all
805 // platforms is fairly involved (will require a HashMap from texture ID
806 // in all ports), and we have not had any complaints, so the logic has
809 cleanupAfterGraphicsCall(false);
812 void WebGLRenderingContext::blendColor(GC3Dfloat red, GC3Dfloat green, GC3Dfloat blue, GC3Dfloat alpha)
816 m_context->blendColor(red, green, blue, alpha);
817 cleanupAfterGraphicsCall(false);
820 void WebGLRenderingContext::blendEquation(GC3Denum mode)
822 if (isContextLost() || !validateBlendEquation(mode))
824 m_context->blendEquation(mode);
825 cleanupAfterGraphicsCall(false);
828 void WebGLRenderingContext::blendEquationSeparate(GC3Denum modeRGB, GC3Denum modeAlpha)
830 if (isContextLost() || !validateBlendEquation(modeRGB) || !validateBlendEquation(modeAlpha))
832 m_context->blendEquationSeparate(modeRGB, modeAlpha);
833 cleanupAfterGraphicsCall(false);
837 void WebGLRenderingContext::blendFunc(GC3Denum sfactor, GC3Denum dfactor)
839 if (isContextLost() || !validateBlendFuncFactors(sfactor, dfactor))
841 m_context->blendFunc(sfactor, dfactor);
842 cleanupAfterGraphicsCall(false);
845 void WebGLRenderingContext::blendFuncSeparate(GC3Denum srcRGB, GC3Denum dstRGB, GC3Denum srcAlpha, GC3Denum dstAlpha)
847 if (isContextLost() || !validateBlendFuncFactors(srcRGB, dstRGB))
849 m_context->blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha);
850 cleanupAfterGraphicsCall(false);
853 void WebGLRenderingContext::bufferData(GC3Denum target, GC3Dsizeiptr size, GC3Denum usage, ExceptionCode& ec)
858 WebGLBuffer* buffer = validateBufferDataParameters(target, usage);
862 m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
865 if (!isErrorGeneratedOnOutOfBoundsAccesses()) {
866 if (!buffer->associateBufferData(size)) {
867 m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
872 m_context->bufferData(target, size, usage);
873 cleanupAfterGraphicsCall(false);
876 void WebGLRenderingContext::bufferData(GC3Denum target, ArrayBuffer* data, GC3Denum usage, ExceptionCode& ec)
881 WebGLBuffer* buffer = validateBufferDataParameters(target, usage);
885 m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
888 if (!isErrorGeneratedOnOutOfBoundsAccesses()) {
889 if (!buffer->associateBufferData(data)) {
890 m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
895 m_context->bufferData(target, data->byteLength(), data->data(), usage);
896 cleanupAfterGraphicsCall(false);
899 void WebGLRenderingContext::bufferData(GC3Denum target, ArrayBufferView* data, GC3Denum usage, ExceptionCode& ec)
904 WebGLBuffer* buffer = validateBufferDataParameters(target, usage);
908 m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
911 if (!isErrorGeneratedOnOutOfBoundsAccesses()) {
912 if (!buffer->associateBufferData(data)) {
913 m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
918 m_context->bufferData(target, data->byteLength(), data->baseAddress(), usage);
919 cleanupAfterGraphicsCall(false);
922 void WebGLRenderingContext::bufferSubData(GC3Denum target, GC3Dintptr offset, ArrayBuffer* data, ExceptionCode& ec)
927 WebGLBuffer* buffer = validateBufferDataParameters(target, GraphicsContext3D::STATIC_DRAW);
931 m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
936 if (!isErrorGeneratedOnOutOfBoundsAccesses()) {
937 if (!buffer->associateBufferSubData(offset, data)) {
938 m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
943 m_context->bufferSubData(target, offset, data->byteLength(), data->data());
944 cleanupAfterGraphicsCall(false);
947 void WebGLRenderingContext::bufferSubData(GC3Denum target, GC3Dintptr offset, ArrayBufferView* data, ExceptionCode& ec)
952 WebGLBuffer* buffer = validateBufferDataParameters(target, GraphicsContext3D::STATIC_DRAW);
956 m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
961 if (!isErrorGeneratedOnOutOfBoundsAccesses()) {
962 if (!buffer->associateBufferSubData(offset, data)) {
963 m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
968 m_context->bufferSubData(target, offset, data->byteLength(), data->baseAddress());
969 cleanupAfterGraphicsCall(false);
972 GC3Denum WebGLRenderingContext::checkFramebufferStatus(GC3Denum target)
975 return GraphicsContext3D::FRAMEBUFFER_UNSUPPORTED;
976 if (target != GraphicsContext3D::FRAMEBUFFER) {
977 m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
980 if (!m_framebufferBinding || !m_framebufferBinding->object())
981 return GraphicsContext3D::FRAMEBUFFER_COMPLETE;
982 if (m_framebufferBinding->isIncomplete(true))
983 return GraphicsContext3D::FRAMEBUFFER_UNSUPPORTED;
984 unsigned long result = m_context->checkFramebufferStatus(target);
985 cleanupAfterGraphicsCall(false);
989 void WebGLRenderingContext::clear(GC3Dbitfield mask)
993 if (mask & ~(GraphicsContext3D::COLOR_BUFFER_BIT | GraphicsContext3D::DEPTH_BUFFER_BIT | GraphicsContext3D::STENCIL_BUFFER_BIT)) {
994 m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
997 if (m_framebufferBinding && !m_framebufferBinding->onAccess(!isResourceSafe())) {
998 m_context->synthesizeGLError(GraphicsContext3D::INVALID_FRAMEBUFFER_OPERATION);
1001 if (!clearIfComposited(mask))
1002 m_context->clear(mask);
1003 cleanupAfterGraphicsCall(true);
1006 void WebGLRenderingContext::clearColor(GC3Dfloat r, GC3Dfloat g, GC3Dfloat b, GC3Dfloat a)
1008 if (isContextLost())
1018 m_clearColor[0] = r;
1019 m_clearColor[1] = g;
1020 m_clearColor[2] = b;
1021 m_clearColor[3] = a;
1022 m_context->clearColor(r, g, b, a);
1023 cleanupAfterGraphicsCall(false);
1026 void WebGLRenderingContext::clearDepth(GC3Dfloat depth)
1028 if (isContextLost())
1030 m_clearDepth = depth;
1031 m_context->clearDepth(depth);
1032 cleanupAfterGraphicsCall(false);
1035 void WebGLRenderingContext::clearStencil(GC3Dint s)
1037 if (isContextLost())
1040 m_context->clearStencil(s);
1041 cleanupAfterGraphicsCall(false);
1044 void WebGLRenderingContext::colorMask(GC3Dboolean red, GC3Dboolean green, GC3Dboolean blue, GC3Dboolean alpha)
1046 if (isContextLost())
1048 m_colorMask[0] = red;
1049 m_colorMask[1] = green;
1050 m_colorMask[2] = blue;
1051 m_colorMask[3] = alpha;
1052 m_context->colorMask(red, green, blue, alpha);
1053 cleanupAfterGraphicsCall(false);
1056 void WebGLRenderingContext::compileShader(WebGLShader* shader, ExceptionCode& ec)
1059 if (isContextLost() || !validateWebGLObject(shader))
1061 m_context->compileShader(objectOrZero(shader));
1062 cleanupAfterGraphicsCall(false);
1065 void WebGLRenderingContext::copyTexImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height, GC3Dint border)
1067 if (isContextLost())
1069 if (!validateTexFuncParameters(target, level, internalformat, width, height, border, internalformat, GraphicsContext3D::UNSIGNED_BYTE))
1071 WebGLTexture* tex = validateTextureBinding(target, true);
1074 if (!isTexInternalFormatColorBufferCombinationValid(internalformat, getBoundFramebufferColorFormat())) {
1075 m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
1078 if (!isGLES2NPOTStrict() && level && WebGLTexture::isNPOT(width, height)) {
1079 m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
1082 if (m_framebufferBinding && !m_framebufferBinding->onAccess(!isResourceSafe())) {
1083 m_context->synthesizeGLError(GraphicsContext3D::INVALID_FRAMEBUFFER_OPERATION);
1086 clearIfComposited();
1087 if (isResourceSafe())
1088 m_context->copyTexImage2D(target, level, internalformat, x, y, width, height, border);
1090 GC3Dint clippedX, clippedY;
1091 GC3Dsizei clippedWidth, clippedHeight;
1092 if (clip2D(x, y, width, height, getBoundFramebufferWidth(), getBoundFramebufferHeight(), &clippedX, &clippedY, &clippedWidth, &clippedHeight)) {
1093 m_context->texImage2DResourceSafe(target, level, internalformat, width, height, border,
1094 internalformat, GraphicsContext3D::UNSIGNED_BYTE, m_unpackAlignment);
1095 if (clippedWidth > 0 && clippedHeight > 0) {
1096 m_context->copyTexSubImage2D(target, level, clippedX - x, clippedY - y,
1097 clippedX, clippedY, clippedWidth, clippedHeight);
1100 m_context->copyTexImage2D(target, level, internalformat, x, y, width, height, border);
1102 // FIXME: if the framebuffer is not complete, none of the below should be executed.
1103 tex->setLevelInfo(target, level, internalformat, width, height, GraphicsContext3D::UNSIGNED_BYTE);
1104 cleanupAfterGraphicsCall(false);
1107 void WebGLRenderingContext::copyTexSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height)
1109 if (isContextLost())
1111 if (!validateTexFuncLevel(target, level))
1113 WebGLTexture* tex = validateTextureBinding(target, true);
1116 if (!validateSize(xoffset, yoffset) || !validateSize(width, height))
1118 if (xoffset + width > tex->getWidth(target, level) || yoffset + height > tex->getHeight(target, level)) {
1119 m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
1122 if (!isTexInternalFormatColorBufferCombinationValid(tex->getInternalFormat(target, level), getBoundFramebufferColorFormat())) {
1123 m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
1126 if (m_framebufferBinding && !m_framebufferBinding->onAccess(!isResourceSafe())) {
1127 m_context->synthesizeGLError(GraphicsContext3D::INVALID_FRAMEBUFFER_OPERATION);
1130 clearIfComposited();
1131 if (isResourceSafe())
1132 m_context->copyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height);
1134 GC3Dint clippedX, clippedY;
1135 GC3Dsizei clippedWidth, clippedHeight;
1136 if (clip2D(x, y, width, height, getBoundFramebufferWidth(), getBoundFramebufferHeight(), &clippedX, &clippedY, &clippedWidth, &clippedHeight)) {
1137 GC3Denum format = tex->getInternalFormat(target, level);
1138 GC3Denum type = tex->getType(target, level);
1139 OwnArrayPtr<unsigned char> zero;
1140 if (width && height) {
1142 GC3Denum error = m_context->computeImageSizeInBytes(format, type, width, height, m_unpackAlignment, &size, 0);
1143 if (error != GraphicsContext3D::NO_ERROR) {
1144 m_context->synthesizeGLError(error);
1147 zero = adoptArrayPtr(new unsigned char[size]);
1149 m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
1152 memset(zero.get(), 0, size);
1154 m_context->texSubImage2D(target, level, xoffset, yoffset, width, height, format, type, zero.get());
1155 if (clippedWidth > 0 && clippedHeight > 0) {
1156 m_context->copyTexSubImage2D(target, level, xoffset + clippedX - x, yoffset + clippedY - y,
1157 clippedX, clippedY, clippedWidth, clippedHeight);
1160 m_context->copyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height);
1162 cleanupAfterGraphicsCall(false);
1165 PassRefPtr<WebGLBuffer> WebGLRenderingContext::createBuffer()
1167 if (isContextLost())
1169 RefPtr<WebGLBuffer> o = WebGLBuffer::create(this);
1174 PassRefPtr<WebGLFramebuffer> WebGLRenderingContext::createFramebuffer()
1176 if (isContextLost())
1178 RefPtr<WebGLFramebuffer> o = WebGLFramebuffer::create(this);
1183 PassRefPtr<WebGLTexture> WebGLRenderingContext::createTexture()
1185 if (isContextLost())
1187 RefPtr<WebGLTexture> o = WebGLTexture::create(this);
1192 PassRefPtr<WebGLProgram> WebGLRenderingContext::createProgram()
1194 if (isContextLost())
1196 RefPtr<WebGLProgram> o = WebGLProgram::create(this);
1201 PassRefPtr<WebGLRenderbuffer> WebGLRenderingContext::createRenderbuffer()
1203 if (isContextLost())
1205 RefPtr<WebGLRenderbuffer> o = WebGLRenderbuffer::create(this);
1210 PassRefPtr<WebGLShader> WebGLRenderingContext::createShader(GC3Denum type, ExceptionCode& ec)
1213 if (isContextLost())
1215 if (type != GraphicsContext3D::VERTEX_SHADER && type != GraphicsContext3D::FRAGMENT_SHADER) {
1216 m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
1220 RefPtr<WebGLShader> o = WebGLShader::create(this, type);
1225 void WebGLRenderingContext::cullFace(GC3Denum mode)
1227 if (isContextLost())
1229 m_context->cullFace(mode);
1230 cleanupAfterGraphicsCall(false);
1233 bool WebGLRenderingContext::deleteObject(WebGLObject* object)
1235 if (isContextLost() || !object)
1237 if (object->context() != this) {
1238 m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
1241 if (object->object())
1242 object->deleteObject();
1246 void WebGLRenderingContext::deleteBuffer(WebGLBuffer* buffer)
1248 if (!deleteObject(buffer))
1250 if (m_boundArrayBuffer == buffer)
1251 m_boundArrayBuffer = 0;
1252 RefPtr<WebGLBuffer> elementArrayBuffer = m_boundVertexArrayObject->getElementArrayBuffer();
1253 if (elementArrayBuffer == buffer)
1254 m_boundVertexArrayObject->setElementArrayBuffer(0);
1255 if (!isGLES2Compliant()) {
1256 WebGLVertexArrayObjectOES::VertexAttribState& state = m_boundVertexArrayObject->getVertexAttribState(0);
1257 if (buffer == state.bufferBinding) {
1258 state.bufferBinding = m_vertexAttrib0Buffer;
1259 state.bytesPerElement = 0;
1261 state.type = GraphicsContext3D::FLOAT;
1262 state.normalized = false;
1264 state.originalStride = 0;
1270 void WebGLRenderingContext::deleteFramebuffer(WebGLFramebuffer* framebuffer)
1272 if (!deleteObject(framebuffer))
1274 if (framebuffer == m_framebufferBinding) {
1275 m_framebufferBinding = 0;
1276 // Have to call bindFramebuffer here to bind back to internal fbo.
1277 m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, 0);
1281 void WebGLRenderingContext::deleteProgram(WebGLProgram* program)
1283 deleteObject(program);
1284 // We don't reset m_currentProgram to 0 here because the deletion of the
1285 // current program is delayed.
1288 void WebGLRenderingContext::deleteRenderbuffer(WebGLRenderbuffer* renderbuffer)
1290 if (!deleteObject(renderbuffer))
1292 if (renderbuffer == m_renderbufferBinding)
1293 m_renderbufferBinding = 0;
1294 if (m_framebufferBinding)
1295 m_framebufferBinding->removeAttachment(renderbuffer);
1298 void WebGLRenderingContext::deleteShader(WebGLShader* shader)
1300 deleteObject(shader);
1303 void WebGLRenderingContext::deleteTexture(WebGLTexture* texture)
1305 if (!deleteObject(texture))
1307 for (size_t i = 0; i < m_textureUnits.size(); ++i) {
1308 if (texture == m_textureUnits[i].m_texture2DBinding)
1309 m_textureUnits[i].m_texture2DBinding = 0;
1310 if (texture == m_textureUnits[i].m_textureCubeMapBinding)
1311 m_textureUnits[i].m_textureCubeMapBinding = 0;
1313 if (m_framebufferBinding)
1314 m_framebufferBinding->removeAttachment(texture);
1317 void WebGLRenderingContext::depthFunc(GC3Denum func)
1319 if (isContextLost())
1321 m_context->depthFunc(func);
1322 cleanupAfterGraphicsCall(false);
1325 void WebGLRenderingContext::depthMask(GC3Dboolean flag)
1327 if (isContextLost())
1330 m_context->depthMask(flag);
1331 cleanupAfterGraphicsCall(false);
1334 void WebGLRenderingContext::depthRange(GC3Dfloat zNear, GC3Dfloat zFar)
1336 if (isContextLost())
1339 m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
1342 m_context->depthRange(zNear, zFar);
1343 cleanupAfterGraphicsCall(false);
1346 void WebGLRenderingContext::detachShader(WebGLProgram* program, WebGLShader* shader, ExceptionCode& ec)
1349 if (isContextLost() || !validateWebGLObject(program) || !validateWebGLObject(shader))
1351 if (!program->detachShader(shader)) {
1352 m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
1355 m_context->detachShader(objectOrZero(program), objectOrZero(shader));
1356 shader->onDetached();
1357 cleanupAfterGraphicsCall(false);
1360 void WebGLRenderingContext::disable(GC3Denum cap)
1362 if (isContextLost() || !validateCapability(cap))
1364 if (cap == GraphicsContext3D::SCISSOR_TEST)
1365 m_scissorEnabled = false;
1366 m_context->disable(cap);
1367 cleanupAfterGraphicsCall(false);
1370 void WebGLRenderingContext::disableVertexAttribArray(GC3Duint index, ExceptionCode& ec)
1373 if (isContextLost())
1375 if (index >= m_maxVertexAttribs) {
1376 m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
1380 WebGLVertexArrayObjectOES::VertexAttribState& state = m_boundVertexArrayObject->getVertexAttribState(index);
1381 state.enabled = false;
1383 if (index > 0 || isGLES2Compliant()) {
1384 m_context->disableVertexAttribArray(index);
1385 cleanupAfterGraphicsCall(false);
1389 bool WebGLRenderingContext::validateElementArraySize(GC3Dsizei count, GC3Denum type, GC3Dintptr offset)
1391 RefPtr<WebGLBuffer> elementArrayBuffer = m_boundVertexArrayObject->getElementArrayBuffer();
1393 if (!elementArrayBuffer)
1399 if (type == GraphicsContext3D::UNSIGNED_SHORT) {
1400 // For an unsigned short array, offset must be divisible by 2 for alignment reasons.
1404 // Make uoffset an element offset.
1407 GC3Dsizeiptr n = elementArrayBuffer->byteLength() / 2;
1408 if (offset > n || count > n - offset)
1410 } else if (type == GraphicsContext3D::UNSIGNED_BYTE) {
1411 GC3Dsizeiptr n = elementArrayBuffer->byteLength();
1412 if (offset > n || count > n - offset)
1418 bool WebGLRenderingContext::validateIndexArrayConservative(GC3Denum type, int& numElementsRequired)
1420 // Performs conservative validation by caching a maximum index of
1421 // the given type per element array buffer. If all of the bound
1422 // array buffers have enough elements to satisfy that maximum
1423 // index, skips the expensive per-draw-call iteration in
1424 // validateIndexArrayPrecise.
1426 RefPtr<WebGLBuffer> elementArrayBuffer = m_boundVertexArrayObject->getElementArrayBuffer();
1428 if (!elementArrayBuffer)
1431 GC3Dsizeiptr numElements = elementArrayBuffer->byteLength();
1432 // The case count==0 is already dealt with in drawElements before validateIndexArrayConservative.
1435 const ArrayBuffer* buffer = elementArrayBuffer->elementArrayBuffer();
1438 int maxIndex = elementArrayBuffer->getCachedMaxIndex(type);
1440 // Compute the maximum index in the entire buffer for the given type of index.
1442 case GraphicsContext3D::UNSIGNED_BYTE: {
1443 const GC3Dubyte* p = static_cast<const GC3Dubyte*>(buffer->data());
1444 for (GC3Dsizeiptr i = 0; i < numElements; i++)
1445 maxIndex = max(maxIndex, static_cast<int>(p[i]));
1448 case GraphicsContext3D::UNSIGNED_SHORT: {
1449 numElements /= sizeof(GC3Dushort);
1450 const GC3Dushort* p = static_cast<const GC3Dushort*>(buffer->data());
1451 for (GC3Dsizeiptr i = 0; i < numElements; i++)
1452 maxIndex = max(maxIndex, static_cast<int>(p[i]));
1458 elementArrayBuffer->setCachedMaxIndex(type, maxIndex);
1461 if (maxIndex >= 0) {
1462 // The number of required elements is one more than the maximum
1463 // index that will be accessed.
1464 numElementsRequired = maxIndex + 1;
1471 bool WebGLRenderingContext::validateIndexArrayPrecise(GC3Dsizei count, GC3Denum type, GC3Dintptr offset, int& numElementsRequired)
1473 ASSERT(count >= 0 && offset >= 0);
1476 RefPtr<WebGLBuffer> elementArrayBuffer = m_boundVertexArrayObject->getElementArrayBuffer();
1478 if (!elementArrayBuffer)
1482 numElementsRequired = 0;
1486 if (!elementArrayBuffer->elementArrayBuffer())
1489 unsigned long uoffset = offset;
1490 unsigned long n = count;
1492 if (type == GraphicsContext3D::UNSIGNED_SHORT) {
1493 // Make uoffset an element offset.
1494 uoffset /= sizeof(GC3Dushort);
1495 const GC3Dushort* p = static_cast<const GC3Dushort*>(elementArrayBuffer->elementArrayBuffer()->data()) + uoffset;
1501 } else if (type == GraphicsContext3D::UNSIGNED_BYTE) {
1502 const GC3Dubyte* p = static_cast<const GC3Dubyte*>(elementArrayBuffer->elementArrayBuffer()->data()) + uoffset;
1510 // Then set the last index in the index array and make sure it is valid.
1511 numElementsRequired = lastIndex + 1;
1512 return numElementsRequired > 0;
1515 bool WebGLRenderingContext::validateRenderingState(int numElementsRequired)
1517 if (!m_currentProgram)
1520 // Look in each enabled vertex attrib and check if they've been bound to a buffer.
1521 for (unsigned i = 0; i < m_maxVertexAttribs; ++i) {
1522 const WebGLVertexArrayObjectOES::VertexAttribState& state = m_boundVertexArrayObject->getVertexAttribState(i);
1524 && (!state.bufferBinding || !state.bufferBinding->object()))
1528 if (numElementsRequired <= 0)
1531 // Look in each consumed vertex attrib (by the current program) and find the smallest buffer size
1532 int smallestNumElements = INT_MAX;
1533 int numActiveAttribLocations = m_currentProgram->numActiveAttribLocations();
1534 for (int i = 0; i < numActiveAttribLocations; ++i) {
1535 int loc = m_currentProgram->getActiveAttribLocation(i);
1536 if (loc >= 0 && loc < static_cast<int>(m_maxVertexAttribs)) {
1537 const WebGLVertexArrayObjectOES::VertexAttribState& state = m_boundVertexArrayObject->getVertexAttribState(loc);
1538 if (state.enabled) {
1539 // Avoid off-by-one errors in numElements computation.
1540 // For the last element, we will only touch the data for the
1541 // element and nothing beyond it.
1542 int bytesRemaining = static_cast<int>(state.bufferBinding->byteLength() - state.offset);
1543 int numElements = 0;
1544 ASSERT(state.stride > 0);
1545 if (bytesRemaining >= state.bytesPerElement)
1546 numElements = 1 + (bytesRemaining - state.bytesPerElement) / state.stride;
1547 if (numElements < smallestNumElements)
1548 smallestNumElements = numElements;
1553 if (smallestNumElements == INT_MAX)
1554 smallestNumElements = 0;
1556 return numElementsRequired <= smallestNumElements;
1559 bool WebGLRenderingContext::validateWebGLObject(WebGLObject* object)
1561 if (!object || !object->object()) {
1562 m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
1565 if (object->context() != this) {
1566 m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
1572 void WebGLRenderingContext::drawArrays(GC3Denum mode, GC3Dint first, GC3Dsizei count, ExceptionCode& ec)
1576 if (isContextLost() || !validateDrawMode(mode))
1579 if (!validateStencilSettings())
1582 if (first < 0 || count < 0) {
1583 m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
1590 if (!isErrorGeneratedOnOutOfBoundsAccesses()) {
1591 // Ensure we have a valid rendering state
1592 CheckedInt<GC3Dint> checkedFirst(first);
1593 CheckedInt<GC3Dint> checkedCount(count);
1594 CheckedInt<GC3Dint> checkedSum = checkedFirst + checkedCount;
1595 if (!checkedSum.valid() || !validateRenderingState(checkedSum.value())) {
1596 m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
1600 if (!validateRenderingState(0)) {
1601 m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
1606 if (m_framebufferBinding && !m_framebufferBinding->onAccess(!isResourceSafe())) {
1607 m_context->synthesizeGLError(GraphicsContext3D::INVALID_FRAMEBUFFER_OPERATION);
1611 clearIfComposited();
1613 bool vertexAttrib0Simulated = false;
1614 if (!isGLES2Compliant())
1615 vertexAttrib0Simulated = simulateVertexAttrib0(first + count - 1);
1616 if (!isGLES2NPOTStrict())
1617 handleNPOTTextures(true);
1618 m_context->drawArrays(mode, first, count);
1619 if (!isGLES2Compliant() && vertexAttrib0Simulated)
1620 restoreStatesAfterVertexAttrib0Simulation();
1621 if (!isGLES2NPOTStrict())
1622 handleNPOTTextures(false);
1623 cleanupAfterGraphicsCall(true);
1626 void WebGLRenderingContext::drawElements(GC3Denum mode, GC3Dsizei count, GC3Denum type, GC3Dintptr offset, ExceptionCode& ec)
1630 if (isContextLost() || !validateDrawMode(mode))
1633 if (!validateStencilSettings())
1637 case GraphicsContext3D::UNSIGNED_BYTE:
1638 case GraphicsContext3D::UNSIGNED_SHORT:
1641 m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
1645 if (count < 0 || offset < 0) {
1646 m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
1653 if (!m_boundVertexArrayObject->getElementArrayBuffer()) {
1654 m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
1658 int numElements = 0;
1659 if (!isErrorGeneratedOnOutOfBoundsAccesses()) {
1660 // Ensure we have a valid rendering state
1661 if (!validateElementArraySize(count, type, offset)) {
1662 m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
1667 if (!validateIndexArrayConservative(type, numElements) || !validateRenderingState(numElements)) {
1668 if (!validateIndexArrayPrecise(count, type, offset, numElements) || !validateRenderingState(numElements)) {
1669 m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
1674 if (!validateRenderingState(0)) {
1675 m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
1680 if (m_framebufferBinding && !m_framebufferBinding->onAccess(!isResourceSafe())) {
1681 m_context->synthesizeGLError(GraphicsContext3D::INVALID_FRAMEBUFFER_OPERATION);
1684 clearIfComposited();
1686 bool vertexAttrib0Simulated = false;
1687 if (!isGLES2Compliant()) {
1689 validateIndexArrayPrecise(count, type, offset, numElements);
1690 vertexAttrib0Simulated = simulateVertexAttrib0(numElements);
1692 if (!isGLES2NPOTStrict())
1693 handleNPOTTextures(true);
1694 m_context->drawElements(mode, count, type, offset);
1695 if (!isGLES2Compliant() && vertexAttrib0Simulated)
1696 restoreStatesAfterVertexAttrib0Simulation();
1697 if (!isGLES2NPOTStrict())
1698 handleNPOTTextures(false);
1699 cleanupAfterGraphicsCall(true);
1702 void WebGLRenderingContext::enable(GC3Denum cap)
1704 if (isContextLost() || !validateCapability(cap))
1706 if (cap == GraphicsContext3D::SCISSOR_TEST)
1707 m_scissorEnabled = true;
1708 m_context->enable(cap);
1709 cleanupAfterGraphicsCall(false);
1712 void WebGLRenderingContext::enableVertexAttribArray(GC3Duint index, ExceptionCode& ec)
1715 if (isContextLost())
1717 if (index >= m_maxVertexAttribs) {
1718 m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
1722 WebGLVertexArrayObjectOES::VertexAttribState& state = m_boundVertexArrayObject->getVertexAttribState(index);
1723 state.enabled = true;
1725 m_context->enableVertexAttribArray(index);
1726 cleanupAfterGraphicsCall(false);
1729 void WebGLRenderingContext::finish()
1731 if (isContextLost())
1733 m_context->finish();
1734 cleanupAfterGraphicsCall(false);
1737 void WebGLRenderingContext::flush()
1739 if (isContextLost())
1742 cleanupAfterGraphicsCall(false);
1745 void WebGLRenderingContext::framebufferRenderbuffer(GC3Denum target, GC3Denum attachment, GC3Denum renderbuffertarget, WebGLRenderbuffer* buffer, ExceptionCode& ec)
1748 if (isContextLost() || !validateFramebufferFuncParameters(target, attachment))
1750 if (renderbuffertarget != GraphicsContext3D::RENDERBUFFER) {
1751 m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
1754 if (buffer && buffer->context() != this) {
1755 m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
1758 // Don't allow the default framebuffer to be mutated; all current
1759 // implementations use an FBO internally in place of the default
1761 if (!m_framebufferBinding || !m_framebufferBinding->object()) {
1762 m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
1765 Platform3DObject bufferObject = objectOrZero(buffer);
1766 bool reattachDepth = false;
1767 bool reattachStencil = false;
1768 bool reattachDepthStencilDepth = false;
1769 bool reattachDepthStencilStencil = false;
1770 switch (attachment) {
1771 case GraphicsContext3D::DEPTH_STENCIL_ATTACHMENT:
1772 m_context->framebufferRenderbuffer(target, GraphicsContext3D::DEPTH_ATTACHMENT, renderbuffertarget, bufferObject);
1773 m_context->framebufferRenderbuffer(target, GraphicsContext3D::STENCIL_ATTACHMENT, renderbuffertarget, bufferObject);
1774 if (!bufferObject) {
1775 reattachDepth = true;
1776 reattachStencil = true;
1779 case GraphicsContext3D::DEPTH_ATTACHMENT:
1780 m_context->framebufferRenderbuffer(target, attachment, renderbuffertarget, objectOrZero(buffer));
1782 reattachDepthStencilDepth = true;
1784 case GraphicsContext3D::STENCIL_ATTACHMENT:
1785 m_context->framebufferRenderbuffer(target, attachment, renderbuffertarget, objectOrZero(buffer));
1787 reattachDepthStencilStencil = true;
1790 m_context->framebufferRenderbuffer(target, attachment, renderbuffertarget, objectOrZero(buffer));
1792 m_framebufferBinding->setAttachment(attachment, buffer);
1793 if (reattachDepth) {
1794 Platform3DObject object = objectOrZero(m_framebufferBinding->getAttachment(GraphicsContext3D::DEPTH_ATTACHMENT));
1796 m_context->framebufferRenderbuffer(target, GraphicsContext3D::DEPTH_ATTACHMENT, renderbuffertarget, object);
1798 if (reattachStencil) {
1799 Platform3DObject object = objectOrZero(m_framebufferBinding->getAttachment(GraphicsContext3D::STENCIL_ATTACHMENT));
1801 m_context->framebufferRenderbuffer(target, GraphicsContext3D::STENCIL_ATTACHMENT, renderbuffertarget, object);
1803 if (reattachDepthStencilDepth) {
1804 Platform3DObject object = objectOrZero(m_framebufferBinding->getAttachment(GraphicsContext3D::DEPTH_STENCIL_ATTACHMENT));
1806 m_context->framebufferRenderbuffer(target, GraphicsContext3D::DEPTH_ATTACHMENT, renderbuffertarget, object);
1808 if (reattachDepthStencilStencil) {
1809 Platform3DObject object = objectOrZero(m_framebufferBinding->getAttachment(GraphicsContext3D::DEPTH_STENCIL_ATTACHMENT));
1811 m_context->framebufferRenderbuffer(target, GraphicsContext3D::STENCIL_ATTACHMENT, renderbuffertarget, object);
1813 cleanupAfterGraphicsCall(false);
1816 void WebGLRenderingContext::framebufferTexture2D(GC3Denum target, GC3Denum attachment, GC3Denum textarget, WebGLTexture* texture, GC3Dint level, ExceptionCode& ec)
1819 if (isContextLost() || !validateFramebufferFuncParameters(target, attachment))
1822 m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
1825 if (texture && texture->context() != this) {
1826 m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
1829 // Don't allow the default framebuffer to be mutated; all current
1830 // implementations use an FBO internally in place of the default
1832 if (!m_framebufferBinding || !m_framebufferBinding->object()) {
1833 m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
1836 m_context->framebufferTexture2D(target, attachment, textarget, objectOrZero(texture), level);
1837 m_framebufferBinding->setAttachment(attachment, textarget, texture, level);
1838 cleanupAfterGraphicsCall(false);
1841 void WebGLRenderingContext::frontFace(GC3Denum mode)
1843 if (isContextLost())
1845 m_context->frontFace(mode);
1846 cleanupAfterGraphicsCall(false);
1849 void WebGLRenderingContext::generateMipmap(GC3Denum target)
1851 if (isContextLost())
1853 WebGLTexture* tex = validateTextureBinding(target, false);
1856 if (!tex->canGenerateMipmaps()) {
1857 m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
1860 // generateMipmap won't work properly if minFilter is not NEAREST_MIPMAP_LINEAR
1861 // on Mac. Remove the hack once this driver bug is fixed.
1863 bool needToResetMinFilter = false;
1864 if (tex->getMinFilter() != GraphicsContext3D::NEAREST_MIPMAP_LINEAR) {
1865 m_context->texParameteri(target, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::NEAREST_MIPMAP_LINEAR);
1866 needToResetMinFilter = true;
1869 m_context->generateMipmap(target);
1871 if (needToResetMinFilter)
1872 m_context->texParameteri(target, GraphicsContext3D::TEXTURE_MIN_FILTER, tex->getMinFilter());
1874 tex->generateMipmapLevelInfo();
1875 cleanupAfterGraphicsCall(false);
1878 PassRefPtr<WebGLActiveInfo> WebGLRenderingContext::getActiveAttrib(WebGLProgram* program, GC3Duint index, ExceptionCode& ec)
1881 if (isContextLost() || !validateWebGLObject(program))
1884 if (!m_context->getActiveAttrib(objectOrZero(program), index, info))
1886 return WebGLActiveInfo::create(info.name, info.type, info.size);
1889 PassRefPtr<WebGLActiveInfo> WebGLRenderingContext::getActiveUniform(WebGLProgram* program, GC3Duint index, ExceptionCode& ec)
1892 if (isContextLost() || !validateWebGLObject(program))
1895 if (!m_context->getActiveUniform(objectOrZero(program), index, info))
1897 if (!isGLES2Compliant())
1898 if (info.size > 1 && !info.name.endsWith("[0]"))
1899 info.name.append("[0]");
1900 return WebGLActiveInfo::create(info.name, info.type, info.size);
1903 bool WebGLRenderingContext::getAttachedShaders(WebGLProgram* program, Vector<WebGLShader*>& shaderObjects, ExceptionCode& ec)
1906 shaderObjects.clear();
1907 if (isContextLost() || !validateWebGLObject(program))
1910 const GC3Denum shaderType[] = {
1911 GraphicsContext3D::VERTEX_SHADER,
1912 GraphicsContext3D::FRAGMENT_SHADER
1914 for (unsigned i = 0; i < sizeof(shaderType) / sizeof(GC3Denum); ++i) {
1915 WebGLShader* shader = program->getAttachedShader(shaderType[i]);
1917 shaderObjects.append(shader);
1922 GC3Dint WebGLRenderingContext::getAttribLocation(WebGLProgram* program, const String& name)
1924 if (isContextLost())
1926 if (!validateString(name))
1928 return m_context->getAttribLocation(objectOrZero(program), name);
1931 WebGLGetInfo WebGLRenderingContext::getBufferParameter(GC3Denum target, GC3Denum pname, ExceptionCode& ec)
1934 if (isContextLost())
1935 return WebGLGetInfo();
1936 if (target != GraphicsContext3D::ARRAY_BUFFER && target != GraphicsContext3D::ELEMENT_ARRAY_BUFFER) {
1937 m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
1938 return WebGLGetInfo();
1941 if (pname != GraphicsContext3D::BUFFER_SIZE && pname != GraphicsContext3D::BUFFER_USAGE) {
1942 m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
1943 return WebGLGetInfo();
1946 WebGLStateRestorer(this, false);
1948 m_context->getBufferParameteriv(target, pname, &value);
1949 if (pname == GraphicsContext3D::BUFFER_SIZE)
1950 return WebGLGetInfo(value);
1951 return WebGLGetInfo(static_cast<unsigned int>(value));
1954 PassRefPtr<WebGLContextAttributes> WebGLRenderingContext::getContextAttributes()
1956 if (isContextLost())
1958 // We always need to return a new WebGLContextAttributes object to
1959 // prevent the user from mutating any cached version.
1960 return WebGLContextAttributes::create(m_context->getContextAttributes());
1963 GC3Denum WebGLRenderingContext::getError()
1965 return m_context->getError();
1968 WebGLExtension* WebGLRenderingContext::getExtension(const String& name)
1970 if (isContextLost())
1973 if (equalIgnoringCase(name, "OES_standard_derivatives")
1974 && m_context->getExtensions()->supports("GL_OES_standard_derivatives")) {
1975 if (!m_oesStandardDerivatives) {
1976 m_context->getExtensions()->ensureEnabled("GL_OES_standard_derivatives");
1977 m_oesStandardDerivatives = OESStandardDerivatives::create(this);
1979 return m_oesStandardDerivatives.get();
1981 if (equalIgnoringCase(name, "OES_texture_float")
1982 && m_context->getExtensions()->supports("GL_OES_texture_float")) {
1983 if (!m_oesTextureFloat) {
1984 m_context->getExtensions()->ensureEnabled("GL_OES_texture_float");
1985 m_oesTextureFloat = OESTextureFloat::create(this);
1987 return m_oesTextureFloat.get();
1989 if (equalIgnoringCase(name, "OES_vertex_array_object")
1990 && m_context->getExtensions()->supports("GL_OES_vertex_array_object")) {
1991 if (!m_oesVertexArrayObject) {
1992 m_context->getExtensions()->ensureEnabled("GL_OES_vertex_array_object");
1993 m_oesVertexArrayObject = OESVertexArrayObject::create(this);
1995 return m_oesVertexArrayObject.get();
1997 if (equalIgnoringCase(name, "WEBKIT_lose_context")) {
1998 if (!m_webkitLoseContext)
1999 m_webkitLoseContext = WebKitLoseContext::create(this);
2000 return m_webkitLoseContext.get();
2006 WebGLGetInfo WebGLRenderingContext::getFramebufferAttachmentParameter(GC3Denum target, GC3Denum attachment, GC3Denum pname, ExceptionCode& ec)
2009 if (isContextLost() || !validateFramebufferFuncParameters(target, attachment))
2010 return WebGLGetInfo();
2012 if (!m_framebufferBinding || !m_framebufferBinding->object() || m_framebufferBinding->isIncomplete(false)) {
2013 m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
2014 return WebGLGetInfo();
2017 WebGLObject* object = m_framebufferBinding->getAttachment(attachment);
2019 if (pname == GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE)
2020 return WebGLGetInfo(GraphicsContext3D::NONE);
2021 // OpenGL ES 2.0 specifies INVALID_ENUM in this case, while desktop GL
2022 // specifies INVALID_OPERATION.
2023 m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
2024 return WebGLGetInfo();
2027 ASSERT(object->isTexture() || object->isRenderbuffer());
2028 if (object->isTexture()) {
2030 case GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
2031 return WebGLGetInfo(GraphicsContext3D::TEXTURE);
2032 case GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
2033 return WebGLGetInfo(PassRefPtr<WebGLTexture>(reinterpret_cast<WebGLTexture*>(object)));
2034 case GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
2035 case GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
2037 WebGLStateRestorer(this, false);
2039 m_context->getFramebufferAttachmentParameteriv(target, attachment, pname, &value);
2040 return WebGLGetInfo(value);
2043 m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
2044 return WebGLGetInfo();
2048 case GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
2049 return WebGLGetInfo(GraphicsContext3D::RENDERBUFFER);
2050 case GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
2051 return WebGLGetInfo(PassRefPtr<WebGLRenderbuffer>(reinterpret_cast<WebGLRenderbuffer*>(object)));
2053 m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
2054 return WebGLGetInfo();
2059 WebGLGetInfo WebGLRenderingContext::getParameter(GC3Denum pname, ExceptionCode& ec)
2062 if (isContextLost())
2063 return WebGLGetInfo();
2064 WebGLStateRestorer(this, false);
2066 case GraphicsContext3D::ACTIVE_TEXTURE:
2067 return getUnsignedIntParameter(pname);
2068 case GraphicsContext3D::ALIASED_LINE_WIDTH_RANGE:
2069 return getWebGLFloatArrayParameter(pname);
2070 case GraphicsContext3D::ALIASED_POINT_SIZE_RANGE:
2071 return getWebGLFloatArrayParameter(pname);
2072 case GraphicsContext3D::ALPHA_BITS:
2073 return getIntParameter(pname);
2074 case GraphicsContext3D::ARRAY_BUFFER_BINDING:
2075 return WebGLGetInfo(PassRefPtr<WebGLBuffer>(m_boundArrayBuffer));
2076 case GraphicsContext3D::BLEND:
2077 return getBooleanParameter(pname);
2078 case GraphicsContext3D::BLEND_COLOR:
2079 return getWebGLFloatArrayParameter(pname);
2080 case GraphicsContext3D::BLEND_DST_ALPHA:
2081 return getUnsignedIntParameter(pname);
2082 case GraphicsContext3D::BLEND_DST_RGB:
2083 return getUnsignedIntParameter(pname);
2084 case GraphicsContext3D::BLEND_EQUATION_ALPHA:
2085 return getUnsignedIntParameter(pname);
2086 case GraphicsContext3D::BLEND_EQUATION_RGB:
2087 return getUnsignedIntParameter(pname);
2088 case GraphicsContext3D::BLEND_SRC_ALPHA:
2089 return getUnsignedIntParameter(pname);
2090 case GraphicsContext3D::BLEND_SRC_RGB:
2091 return getUnsignedIntParameter(pname);
2092 case GraphicsContext3D::BLUE_BITS:
2093 return getIntParameter(pname);
2094 case GraphicsContext3D::COLOR_CLEAR_VALUE:
2095 return getWebGLFloatArrayParameter(pname);
2096 case GraphicsContext3D::COLOR_WRITEMASK:
2097 return getBooleanArrayParameter(pname);
2098 case GraphicsContext3D::COMPRESSED_TEXTURE_FORMATS:
2099 // Defined as null in the spec
2100 return WebGLGetInfo();
2101 case GraphicsContext3D::CULL_FACE:
2102 return getBooleanParameter(pname);
2103 case GraphicsContext3D::CULL_FACE_MODE:
2104 return getUnsignedIntParameter(pname);
2105 case GraphicsContext3D::CURRENT_PROGRAM:
2106 return WebGLGetInfo(PassRefPtr<WebGLProgram>(m_currentProgram));
2107 case GraphicsContext3D::DEPTH_BITS:
2108 return getIntParameter(pname);
2109 case GraphicsContext3D::DEPTH_CLEAR_VALUE:
2110 return getFloatParameter(pname);
2111 case GraphicsContext3D::DEPTH_FUNC:
2112 return getUnsignedIntParameter(pname);
2113 case GraphicsContext3D::DEPTH_RANGE:
2114 return getWebGLFloatArrayParameter(pname);
2115 case GraphicsContext3D::DEPTH_TEST:
2116 return getBooleanParameter(pname);
2117 case GraphicsContext3D::DEPTH_WRITEMASK:
2118 return getBooleanParameter(pname);
2119 case GraphicsContext3D::DITHER:
2120 return getBooleanParameter(pname);
2121 case GraphicsContext3D::ELEMENT_ARRAY_BUFFER_BINDING:
2122 return WebGLGetInfo(PassRefPtr<WebGLBuffer>(m_boundVertexArrayObject->getElementArrayBuffer()));
2123 case GraphicsContext3D::FRAMEBUFFER_BINDING:
2124 return WebGLGetInfo(PassRefPtr<WebGLFramebuffer>(m_framebufferBinding));
2125 case GraphicsContext3D::FRONT_FACE:
2126 return getUnsignedIntParameter(pname);
2127 case GraphicsContext3D::GENERATE_MIPMAP_HINT:
2128 return getUnsignedIntParameter(pname);
2129 case GraphicsContext3D::GREEN_BITS:
2130 return getIntParameter(pname);
2131 case GraphicsContext3D::LINE_WIDTH:
2132 return getFloatParameter(pname);
2133 case GraphicsContext3D::MAX_COMBINED_TEXTURE_IMAGE_UNITS:
2134 return getIntParameter(pname);
2135 case GraphicsContext3D::MAX_CUBE_MAP_TEXTURE_SIZE:
2136 return getIntParameter(pname);
2137 case GraphicsContext3D::MAX_FRAGMENT_UNIFORM_VECTORS:
2138 return getIntParameter(pname);
2139 case GraphicsContext3D::MAX_RENDERBUFFER_SIZE:
2140 return getIntParameter(pname);
2141 case GraphicsContext3D::MAX_TEXTURE_IMAGE_UNITS:
2142 return getIntParameter(pname);
2143 case GraphicsContext3D::MAX_TEXTURE_SIZE:
2144 return getIntParameter(pname);
2145 case GraphicsContext3D::MAX_VARYING_VECTORS:
2146 return getIntParameter(pname);
2147 case GraphicsContext3D::MAX_VERTEX_ATTRIBS:
2148 return getIntParameter(pname);
2149 case GraphicsContext3D::MAX_VERTEX_TEXTURE_IMAGE_UNITS:
2150 return getIntParameter(pname);
2151 case GraphicsContext3D::MAX_VERTEX_UNIFORM_VECTORS:
2152 return getIntParameter(pname);
2153 case GraphicsContext3D::MAX_VIEWPORT_DIMS:
2154 return getWebGLIntArrayParameter(pname);
2155 case GraphicsContext3D::NUM_COMPRESSED_TEXTURE_FORMATS:
2156 // WebGL 1.0 specifies that there are no compressed texture formats.
2157 return WebGLGetInfo(static_cast<int>(0));
2158 case GraphicsContext3D::NUM_SHADER_BINARY_FORMATS:
2159 // FIXME: should we always return 0 for this?
2160 return getIntParameter(pname);
2161 case GraphicsContext3D::PACK_ALIGNMENT:
2162 return getIntParameter(pname);
2163 case GraphicsContext3D::POLYGON_OFFSET_FACTOR:
2164 return getFloatParameter(pname);
2165 case GraphicsContext3D::POLYGON_OFFSET_FILL:
2166 return getBooleanParameter(pname);
2167 case GraphicsContext3D::POLYGON_OFFSET_UNITS:
2168 return getFloatParameter(pname);
2169 case GraphicsContext3D::RED_BITS:
2170 return getIntParameter(pname);
2171 case GraphicsContext3D::RENDERBUFFER_BINDING:
2172 return WebGLGetInfo(PassRefPtr<WebGLRenderbuffer>(m_renderbufferBinding));
2173 case GraphicsContext3D::RENDERER:
2174 return WebGLGetInfo(m_context->getString(GraphicsContext3D::RENDERER));
2175 case GraphicsContext3D::SAMPLE_BUFFERS:
2176 return getIntParameter(pname);
2177 case GraphicsContext3D::SAMPLE_COVERAGE_INVERT:
2178 return getBooleanParameter(pname);
2179 case GraphicsContext3D::SAMPLE_COVERAGE_VALUE:
2180 return getFloatParameter(pname);
2181 case GraphicsContext3D::SAMPLES:
2182 return getIntParameter(pname);
2183 case GraphicsContext3D::SCISSOR_BOX:
2184 return getWebGLIntArrayParameter(pname);
2185 case GraphicsContext3D::SCISSOR_TEST:
2186 return getBooleanParameter(pname);
2187 case GraphicsContext3D::SHADING_LANGUAGE_VERSION:
2188 return WebGLGetInfo("WebGL GLSL ES 1.0 (" + m_context->getString(GraphicsContext3D::SHADING_LANGUAGE_VERSION) + ")");
2189 case GraphicsContext3D::STENCIL_BACK_FAIL:
2190 return getUnsignedIntParameter(pname);
2191 case GraphicsContext3D::STENCIL_BACK_FUNC:
2192 return getUnsignedIntParameter(pname);
2193 case GraphicsContext3D::STENCIL_BACK_PASS_DEPTH_FAIL:
2194 return getUnsignedIntParameter(pname);
2195 case GraphicsContext3D::STENCIL_BACK_PASS_DEPTH_PASS:
2196 return getUnsignedIntParameter(pname);
2197 case GraphicsContext3D::STENCIL_BACK_REF:
2198 return getIntParameter(pname);
2199 case GraphicsContext3D::STENCIL_BACK_VALUE_MASK:
2200 return getUnsignedIntParameter(pname);
2201 case GraphicsContext3D::STENCIL_BACK_WRITEMASK:
2202 return getUnsignedIntParameter(pname);
2203 case GraphicsContext3D::STENCIL_BITS:
2204 return getIntParameter(pname);
2205 case GraphicsContext3D::STENCIL_CLEAR_VALUE:
2206 return getIntParameter(pname);
2207 case GraphicsContext3D::STENCIL_FAIL:
2208 return getUnsignedIntParameter(pname);
2209 case GraphicsContext3D::STENCIL_FUNC:
2210 return getUnsignedIntParameter(pname);
2211 case GraphicsContext3D::STENCIL_PASS_DEPTH_FAIL:
2212 return getUnsignedIntParameter(pname);
2213 case GraphicsContext3D::STENCIL_PASS_DEPTH_PASS:
2214 return getUnsignedIntParameter(pname);
2215 case GraphicsContext3D::STENCIL_REF:
2216 return getIntParameter(pname);
2217 case GraphicsContext3D::STENCIL_TEST:
2218 return getBooleanParameter(pname);
2219 case GraphicsContext3D::STENCIL_VALUE_MASK:
2220 return getUnsignedIntParameter(pname);
2221 case GraphicsContext3D::STENCIL_WRITEMASK:
2222 return getUnsignedIntParameter(pname);
2223 case GraphicsContext3D::SUBPIXEL_BITS:
2224 return getIntParameter(pname);
2225 case GraphicsContext3D::TEXTURE_BINDING_2D:
2226 return WebGLGetInfo(PassRefPtr<WebGLTexture>(m_textureUnits[m_activeTextureUnit].m_texture2DBinding));
2227 case GraphicsContext3D::TEXTURE_BINDING_CUBE_MAP:
2228 return WebGLGetInfo(PassRefPtr<WebGLTexture>(m_textureUnits[m_activeTextureUnit].m_textureCubeMapBinding));
2229 case GraphicsContext3D::UNPACK_ALIGNMENT:
2230 return getIntParameter(pname);
2231 case GraphicsContext3D::UNPACK_FLIP_Y_WEBGL:
2232 return WebGLGetInfo(m_unpackFlipY);
2233 case GraphicsContext3D::UNPACK_PREMULTIPLY_ALPHA_WEBGL:
2234 return WebGLGetInfo(m_unpackPremultiplyAlpha);
2235 case GraphicsContext3D::UNPACK_COLORSPACE_CONVERSION_WEBGL:
2236 return WebGLGetInfo(m_unpackColorspaceConversion);
2237 case GraphicsContext3D::VENDOR:
2238 return WebGLGetInfo("Webkit (" + m_context->getString(GraphicsContext3D::VENDOR) + ")");
2239 case GraphicsContext3D::VERSION:
2240 return WebGLGetInfo("WebGL 1.0 (" + m_context->getString(GraphicsContext3D::VERSION) + ")");
2241 case GraphicsContext3D::VIEWPORT:
2242 return getWebGLIntArrayParameter(pname);
2243 case Extensions3D::FRAGMENT_SHADER_DERIVATIVE_HINT_OES: // OES_standard_derivatives
2244 if (m_oesStandardDerivatives)
2245 return getUnsignedIntParameter(Extensions3D::FRAGMENT_SHADER_DERIVATIVE_HINT_OES);
2246 m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
2247 return WebGLGetInfo();
2248 case Extensions3D::VERTEX_ARRAY_BINDING_OES: // OES_vertex_array_object
2249 if (m_oesVertexArrayObject) {
2250 if (!m_boundVertexArrayObject->isDefaultObject())
2251 return WebGLGetInfo(PassRefPtr<WebGLVertexArrayObjectOES>(m_boundVertexArrayObject));
2252 return WebGLGetInfo();
2254 m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
2255 return WebGLGetInfo();
2257 m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
2258 return WebGLGetInfo();
2262 WebGLGetInfo WebGLRenderingContext::getProgramParameter(WebGLProgram* program, GC3Denum pname, ExceptionCode& ec)
2265 if (isContextLost() || !validateWebGLObject(program))
2266 return WebGLGetInfo();
2268 WebGLStateRestorer(this, false);
2271 case GraphicsContext3D::DELETE_STATUS:
2272 return WebGLGetInfo(program->isDeleted());
2273 case GraphicsContext3D::VALIDATE_STATUS:
2274 m_context->getProgramiv(objectOrZero(program), pname, &value);
2275 return WebGLGetInfo(static_cast<bool>(value));
2276 case GraphicsContext3D::LINK_STATUS:
2277 return WebGLGetInfo(program->getLinkStatus());
2278 case GraphicsContext3D::ATTACHED_SHADERS:
2279 case GraphicsContext3D::ACTIVE_ATTRIBUTES:
2280 case GraphicsContext3D::ACTIVE_UNIFORMS:
2281 m_context->getProgramiv(objectOrZero(program), pname, &value);
2282 return WebGLGetInfo(value);
2284 m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
2285 return WebGLGetInfo();
2289 String WebGLRenderingContext::getProgramInfoLog(WebGLProgram* program, ExceptionCode& ec)
2292 if (isContextLost())
2294 if (!validateWebGLObject(program))
2296 WebGLStateRestorer(this, false);
2297 return m_context->getProgramInfoLog(objectOrZero(program));
2300 WebGLGetInfo WebGLRenderingContext::getRenderbufferParameter(GC3Denum target, GC3Denum pname, ExceptionCode& ec)
2303 if (isContextLost())
2304 return WebGLGetInfo();
2305 if (target != GraphicsContext3D::RENDERBUFFER) {
2306 m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
2307 return WebGLGetInfo();
2309 if (!m_renderbufferBinding || !m_renderbufferBinding->object()) {
2310 m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
2311 return WebGLGetInfo();
2314 if (m_renderbufferBinding->getInternalFormat() == GraphicsContext3D::DEPTH_STENCIL
2315 && !m_renderbufferBinding->isValid()) {
2316 ASSERT(!isDepthStencilSupported());
2319 case GraphicsContext3D::RENDERBUFFER_WIDTH:
2320 value = m_renderbufferBinding->getWidth();
2322 case GraphicsContext3D::RENDERBUFFER_HEIGHT:
2323 value = m_renderbufferBinding->getHeight();
2325 case GraphicsContext3D::RENDERBUFFER_RED_SIZE:
2326 case GraphicsContext3D::RENDERBUFFER_GREEN_SIZE:
2327 case GraphicsContext3D::RENDERBUFFER_BLUE_SIZE:
2328 case GraphicsContext3D::RENDERBUFFER_ALPHA_SIZE:
2331 case GraphicsContext3D::RENDERBUFFER_DEPTH_SIZE:
2334 case GraphicsContext3D::RENDERBUFFER_STENCIL_SIZE:
2337 case GraphicsContext3D::RENDERBUFFER_INTERNAL_FORMAT:
2338 return WebGLGetInfo(m_renderbufferBinding->getInternalFormat());
2340 m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
2341 return WebGLGetInfo();
2343 return WebGLGetInfo(value);
2346 WebGLStateRestorer(this, false);
2349 case GraphicsContext3D::RENDERBUFFER_WIDTH:
2350 case GraphicsContext3D::RENDERBUFFER_HEIGHT:
2351 case GraphicsContext3D::RENDERBUFFER_RED_SIZE:
2352 case GraphicsContext3D::RENDERBUFFER_GREEN_SIZE:
2353 case GraphicsContext3D::RENDERBUFFER_BLUE_SIZE:
2354 case GraphicsContext3D::RENDERBUFFER_ALPHA_SIZE:
2355 case GraphicsContext3D::RENDERBUFFER_DEPTH_SIZE:
2356 case GraphicsContext3D::RENDERBUFFER_STENCIL_SIZE:
2357 m_context->getRenderbufferParameteriv(target, pname, &value);
2358 return WebGLGetInfo(value);
2359 case GraphicsContext3D::RENDERBUFFER_INTERNAL_FORMAT:
2360 return WebGLGetInfo(m_renderbufferBinding->getInternalFormat());
2362 m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
2363 return WebGLGetInfo();
2367 WebGLGetInfo WebGLRenderingContext::getShaderParameter(WebGLShader* shader, GC3Denum pname, ExceptionCode& ec)
2370 if (isContextLost() || !validateWebGLObject(shader))
2371 return WebGLGetInfo();
2372 WebGLStateRestorer(this, false);
2375 case GraphicsContext3D::DELETE_STATUS:
2376 return WebGLGetInfo(shader->isDeleted());
2377 case GraphicsContext3D::COMPILE_STATUS:
2378 m_context->getShaderiv(objectOrZero(shader), pname, &value);
2379 return WebGLGetInfo(static_cast<bool>(value));
2380 case GraphicsContext3D::SHADER_TYPE:
2381 m_context->getShaderiv(objectOrZero(shader), pname, &value);
2382 return WebGLGetInfo(static_cast<unsigned int>(value));
2384 m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
2385 return WebGLGetInfo();
2389 String WebGLRenderingContext::getShaderInfoLog(WebGLShader* shader, ExceptionCode& ec)
2392 if (isContextLost())
2394 if (!validateWebGLObject(shader))
2396 WebGLStateRestorer(this, false);
2397 return m_context->getShaderInfoLog(objectOrZero(shader));
2400 String WebGLRenderingContext::getShaderSource(WebGLShader* shader, ExceptionCode& ec)
2403 if (isContextLost())
2405 if (!validateWebGLObject(shader))
2407 return shader->getSource();
2410 Vector<String> WebGLRenderingContext::getSupportedExtensions()
2412 Vector<String> result;
2413 if (m_context->getExtensions()->supports("GL_OES_texture_float"))
2414 result.append("OES_texture_float");
2415 if (m_context->getExtensions()->supports("GL_OES_standard_derivatives"))
2416 result.append("OES_standard_derivatives");
2417 if (m_context->getExtensions()->supports("GL_OES_vertex_array_object"))
2418 result.append("OES_vertex_array_object");
2419 result.append("WEBKIT_lose_context");
2423 WebGLGetInfo WebGLRenderingContext::getTexParameter(GC3Denum target, GC3Denum pname, ExceptionCode& ec)
2426 if (isContextLost())
2427 return WebGLGetInfo();
2428 WebGLTexture* tex = validateTextureBinding(target, false);
2430 return WebGLGetInfo();
2431 WebGLStateRestorer(this, false);
2434 case GraphicsContext3D::TEXTURE_MAG_FILTER:
2435 case GraphicsContext3D::TEXTURE_MIN_FILTER:
2436 case GraphicsContext3D::TEXTURE_WRAP_S:
2437 case GraphicsContext3D::TEXTURE_WRAP_T:
2438 m_context->getTexParameteriv(target, pname, &value);
2439 return WebGLGetInfo(static_cast<unsigned int>(value));
2441 m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
2442 return WebGLGetInfo();
2446 WebGLGetInfo WebGLRenderingContext::getUniform(WebGLProgram* program, const WebGLUniformLocation* uniformLocation, ExceptionCode& ec)
2449 if (isContextLost() || !validateWebGLObject(program))
2450 return WebGLGetInfo();
2451 if (!uniformLocation || uniformLocation->program() != program) {
2452 m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
2453 return WebGLGetInfo();
2455 GC3Dint location = uniformLocation->location();
2457 WebGLStateRestorer(this, false);
2458 // FIXME: make this more efficient using WebGLUniformLocation and caching types in it
2459 GC3Dint activeUniforms = 0;
2460 m_context->getProgramiv(objectOrZero(program), GraphicsContext3D::ACTIVE_UNIFORMS, &activeUniforms);
2461 for (GC3Dint i = 0; i < activeUniforms; i++) {
2463 if (!m_context->getActiveUniform(objectOrZero(program), i, info))
2464 return WebGLGetInfo();
2465 // Strip "[0]" from the name if it's an array.
2466 if (info.size > 1 && info.name.endsWith("[0]"))
2467 info.name = info.name.left(info.name.length() - 3);
2468 // If it's an array, we need to iterate through each element, appending "[index]" to the name.
2469 for (GC3Dint index = 0; index < info.size; ++index) {
2470 String name = info.name;
2471 if (info.size > 1 && index >= 1) {
2473 name.append(String::number(index));
2476 // Now need to look this up by name again to find its location
2477 GC3Dint loc = m_context->getUniformLocation(objectOrZero(program), name);
2478 if (loc == location) {
2479 // Found it. Use the type in the ActiveInfo to determine the return type.
2481 unsigned int length;
2482 switch (info.type) {
2483 case GraphicsContext3D::BOOL:
2484 baseType = GraphicsContext3D::BOOL;
2487 case GraphicsContext3D::BOOL_VEC2:
2488 baseType = GraphicsContext3D::BOOL;
2491 case GraphicsContext3D::BOOL_VEC3:
2492 baseType = GraphicsContext3D::BOOL;
2495 case GraphicsContext3D::BOOL_VEC4:
2496 baseType = GraphicsContext3D::BOOL;
2499 case GraphicsContext3D::INT:
2500 baseType = GraphicsContext3D::INT;
2503 case GraphicsContext3D::INT_VEC2:
2504 baseType = GraphicsContext3D::INT;
2507 case GraphicsContext3D::INT_VEC3:
2508 baseType = GraphicsContext3D::INT;
2511 case GraphicsContext3D::INT_VEC4:
2512 baseType = GraphicsContext3D::INT;
2515 case GraphicsContext3D::FLOAT:
2516 baseType = GraphicsContext3D::FLOAT;
2519 case GraphicsContext3D::FLOAT_VEC2:
2520 baseType = GraphicsContext3D::FLOAT;
2523 case GraphicsContext3D::FLOAT_VEC3:
2524 baseType = GraphicsContext3D::FLOAT;
2527 case GraphicsContext3D::FLOAT_VEC4:
2528 baseType = GraphicsContext3D::FLOAT;
2531 case GraphicsContext3D::FLOAT_MAT2:
2532 baseType = GraphicsContext3D::FLOAT;
2535 case GraphicsContext3D::FLOAT_MAT3:
2536 baseType = GraphicsContext3D::FLOAT;
2539 case GraphicsContext3D::FLOAT_MAT4:
2540 baseType = GraphicsContext3D::FLOAT;
2543 case GraphicsContext3D::SAMPLER_2D:
2544 case GraphicsContext3D::SAMPLER_CUBE:
2545 baseType = GraphicsContext3D::INT;
2549 // Can't handle this type
2550 m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
2551 return WebGLGetInfo();
2554 case GraphicsContext3D::FLOAT: {
2555 GC3Dfloat value[16] = {0};
2556 m_context->getUniformfv(objectOrZero(program), location, value);
2558 return WebGLGetInfo(value[0]);
2559 return WebGLGetInfo(Float32Array::create(value, length));
2561 case GraphicsContext3D::INT: {
2562 GC3Dint value[4] = {0};
2563 m_context->getUniformiv(objectOrZero(program), location, value);
2565 return WebGLGetInfo(value[0]);
2566 return WebGLGetInfo(Int32Array::create(value, length));
2568 case GraphicsContext3D::BOOL: {
2569 GC3Dint value[4] = {0};
2570 m_context->getUniformiv(objectOrZero(program), location, value);
2572 bool boolValue[16] = {0};
2573 for (unsigned j = 0; j < length; j++)
2574 boolValue[j] = static_cast<bool>(value[j]);
2575 return WebGLGetInfo(boolValue, length);
2577 return WebGLGetInfo(static_cast<bool>(value[0]));
2585 // If we get here, something went wrong in our unfortunately complex logic above
2586 m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
2587 return WebGLGetInfo();
2590 PassRefPtr<WebGLUniformLocation> WebGLRenderingContext::getUniformLocation(WebGLProgram* program, const String& name, ExceptionCode& ec)
2593 if (isContextLost() || !validateWebGLObject(program))
2595 if (!validateString(name))
2597 WebGLStateRestorer(this, false);
2598 GC3Dint uniformLocation = m_context->getUniformLocation(objectOrZero(program), name);
2599 if (uniformLocation == -1)
2601 return WebGLUniformLocation::create(program, uniformLocation);
2604 WebGLGetInfo WebGLRenderingContext::getVertexAttrib(GC3Duint index, GC3Denum pname, ExceptionCode& ec)
2607 if (isContextLost())
2608 return WebGLGetInfo();
2609 WebGLStateRestorer(this, false);
2610 if (index >= m_maxVertexAttribs) {
2611 m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
2612 return WebGLGetInfo();
2614 const WebGLVertexArrayObjectOES::VertexAttribState& state = m_boundVertexArrayObject->getVertexAttribState(index);
2616 case GraphicsContext3D::VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
2617 if ((!isGLES2Compliant() && !index && m_boundVertexArrayObject->getVertexAttribState(0).bufferBinding == m_vertexAttrib0Buffer)
2618 || !state.bufferBinding
2619 || !state.bufferBinding->object())
2620 return WebGLGetInfo();
2621 return WebGLGetInfo(PassRefPtr<WebGLBuffer>(state.bufferBinding));
2622 case GraphicsContext3D::VERTEX_ATTRIB_ARRAY_ENABLED:
2623 return WebGLGetInfo(state.enabled);
2624 case GraphicsContext3D::VERTEX_ATTRIB_ARRAY_NORMALIZED:
2625 return WebGLGetInfo(state.normalized);
2626 case GraphicsContext3D::VERTEX_ATTRIB_ARRAY_SIZE:
2627 return WebGLGetInfo(state.size);
2628 case GraphicsContext3D::VERTEX_ATTRIB_ARRAY_STRIDE:
2629 return WebGLGetInfo(state.originalStride);
2630 case GraphicsContext3D::VERTEX_ATTRIB_ARRAY_TYPE:
2631 return WebGLGetInfo(state.type);
2632 case GraphicsContext3D::CURRENT_VERTEX_ATTRIB:
2633 return WebGLGetInfo(Float32Array::create(m_vertexAttribValue[index].value, 4));
2635 m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
2636 return WebGLGetInfo();
2640 GC3Dsizeiptr WebGLRenderingContext::getVertexAttribOffset(GC3Duint index, GC3Denum pname)
2642 if (isContextLost())
2644 GC3Dsizeiptr result = m_context->getVertexAttribOffset(index, pname);
2645 cleanupAfterGraphicsCall(false);
2649 void WebGLRenderingContext::hint(GC3Denum target, GC3Denum mode)
2651 if (isContextLost())
2653 bool isValid = false;
2655 case GraphicsContext3D::GENERATE_MIPMAP_HINT:
2658 case Extensions3D::FRAGMENT_SHADER_DERIVATIVE_HINT_OES: // OES_standard_derivatives
2659 if (m_oesStandardDerivatives)
2664 m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
2667 m_context->hint(target, mode);
2668 cleanupAfterGraphicsCall(false);
2671 GC3Dboolean WebGLRenderingContext::isBuffer(WebGLBuffer* buffer)
2673 if (!buffer || isContextLost())
2676 if (!buffer->hasEverBeenBound())
2679 return m_context->isBuffer(buffer->object());
2682 bool WebGLRenderingContext::isContextLost()
2684 return m_contextLost;
2687 GC3Dboolean WebGLRenderingContext::isEnabled(GC3Denum cap)
2689 if (!validateCapability(cap) || isContextLost())
2691 return m_context->isEnabled(cap);
2694 GC3Dboolean WebGLRenderingContext::isFramebuffer(WebGLFramebuffer* framebuffer)
2696 if (!framebuffer || isContextLost())
2699 if (!framebuffer->hasEverBeenBound())
2702 return m_context->isFramebuffer(framebuffer->object());
2705 GC3Dboolean WebGLRenderingContext::isProgram(WebGLProgram* program)
2707 if (!program || isContextLost())
2710 return m_context->isProgram(program->object());
2713 GC3Dboolean WebGLRenderingContext::isRenderbuffer(WebGLRenderbuffer* renderbuffer)
2715 if (!renderbuffer || isContextLost())
2718 if (!renderbuffer->hasEverBeenBound())
2721 return m_context->isRenderbuffer(renderbuffer->object());
2724 GC3Dboolean WebGLRenderingContext::isShader(WebGLShader* shader)
2726 if (!shader || isContextLost())
2729 return m_context->isShader(shader->object());
2732 GC3Dboolean WebGLRenderingContext::isTexture(WebGLTexture* texture)
2734 if (!texture || isContextLost())
2737 if (!texture->hasEverBeenBound())
2740 return m_context->isTexture(texture->object());
2743 void WebGLRenderingContext::lineWidth(GC3Dfloat width)
2745 if (isContextLost())
2747 m_context->lineWidth(width);
2748 cleanupAfterGraphicsCall(false);
2751 void WebGLRenderingContext::linkProgram(WebGLProgram* program, ExceptionCode& ec)
2754 if (isContextLost() || !validateWebGLObject(program))
2756 if (!isGLES2Compliant()) {
2757 if (!program->getAttachedShader(GraphicsContext3D::VERTEX_SHADER) || !program->getAttachedShader(GraphicsContext3D::FRAGMENT_SHADER)) {
2758 program->setLinkStatus(false);
2763 m_context->linkProgram(objectOrZero(program));
2764 program->increaseLinkCount();
2765 // cache link status
2767 m_context->getProgramiv(objectOrZero(program), GraphicsContext3D::LINK_STATUS, &value);
2768 program->setLinkStatus(static_cast<bool>(value));
2769 // Need to cache link status before caching active attribute locations.
2770 program->cacheActiveAttribLocations();
2771 cleanupAfterGraphicsCall(false);
2774 void WebGLRenderingContext::pixelStorei(GC3Denum pname, GC3Dint param)
2776 if (isContextLost())
2779 case GraphicsContext3D::UNPACK_FLIP_Y_WEBGL:
2780 m_unpackFlipY = param;
2782 case GraphicsContext3D::UNPACK_PREMULTIPLY_ALPHA_WEBGL:
2783 m_unpackPremultiplyAlpha = param;
2785 case GraphicsContext3D::UNPACK_COLORSPACE_CONVERSION_WEBGL:
2786 if (param == GraphicsContext3D::BROWSER_DEFAULT_WEBGL || param == GraphicsContext3D::NONE)
2787 m_unpackColorspaceConversion = static_cast<GC3Denum>(param);
2789 m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
2793 case GraphicsContext3D::PACK_ALIGNMENT:
2794 case GraphicsContext3D::UNPACK_ALIGNMENT:
2795 if (param == 1 || param == 2 || param == 4 || param == 8) {
2796 if (pname == GraphicsContext3D::PACK_ALIGNMENT)
2797 m_packAlignment = param;
2798 else // GraphicsContext3D::UNPACK_ALIGNMENT:
2799 m_unpackAlignment = param;
2800 m_context->pixelStorei(pname, param);
2801 cleanupAfterGraphicsCall(false);
2803 m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
2808 m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
2813 void WebGLRenderingContext::polygonOffset(GC3Dfloat factor, GC3Dfloat units)
2815 if (isContextLost())
2817 m_context->polygonOffset(factor, units);
2818 cleanupAfterGraphicsCall(false);
2821 void WebGLRenderingContext::readPixels(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height, GC3Denum format, GC3Denum type, ArrayBufferView* pixels, ExceptionCode&)
2823 if (isContextLost())
2825 // Due to WebGL's same-origin restrictions, it is not possible to
2826 // taint the origin using the WebGL API.
2827 ASSERT(canvas()->originClean());
2828 // Validate input parameters.
2830 m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
2834 case GraphicsContext3D::ALPHA:
2835 case GraphicsContext3D::RGB:
2836 case GraphicsContext3D::RGBA:
2839 m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
2843 case GraphicsContext3D::UNSIGNED_BYTE:
2844 case GraphicsContext3D::UNSIGNED_SHORT_5_6_5:
2845 case GraphicsContext3D::UNSIGNED_SHORT_4_4_4_4:
2846 case GraphicsContext3D::UNSIGNED_SHORT_5_5_5_1:
2849 m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
2852 if (format != GraphicsContext3D::RGBA || type != GraphicsContext3D::UNSIGNED_BYTE) {
2853 m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
2856 // Validate array type against pixel type.
2857 if (!pixels->isUnsignedByteArray()) {
2858 m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
2861 if (m_framebufferBinding && !m_framebufferBinding->onAccess(!isResourceSafe())) {
2862 m_context->synthesizeGLError(GraphicsContext3D::INVALID_FRAMEBUFFER_OPERATION);
2865 // Calculate array size, taking into consideration of PACK_ALIGNMENT.
2866 unsigned int totalBytesRequired;
2867 unsigned int padding;
2868 GC3Denum error = m_context->computeImageSizeInBytes(format, type, width, height, m_packAlignment, &totalBytesRequired, &padding);
2869 if (error != GraphicsContext3D::NO_ERROR) {
2870 m_context->synthesizeGLError(error);
2873 if (pixels->byteLength() < totalBytesRequired) {
2874 m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
2877 clearIfComposited();
2878 void* data = pixels->baseAddress();
2879 m_context->readPixels(x, y, width, height, format, type, data);
2881 // FIXME: remove this section when GL driver bug on Mac is fixed, i.e.,
2882 // when alpha is off, readPixels should set alpha to 255 instead of 0.
2883 if (!m_context->getContextAttributes().alpha) {
2884 unsigned char* pixels = reinterpret_cast<unsigned char*>(data);
2885 for (GC3Dsizei iy = 0; iy < height; ++iy) {
2886 for (GC3Dsizei ix = 0; ix < width; ++ix) {
2894 cleanupAfterGraphicsCall(false);
2897 void WebGLRenderingContext::releaseShaderCompiler()
2899 if (isContextLost())
2901 m_context->releaseShaderCompiler();
2902 cleanupAfterGraphicsCall(false);
2905 void WebGLRenderingContext::renderbufferStorage(GC3Denum target, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height)
2907 if (isContextLost())
2909 if (target != GraphicsContext3D::RENDERBUFFER) {
2910 m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
2913 if (!m_renderbufferBinding || !m_renderbufferBinding->object()) {
2914 m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
2917 if (!validateSize(width, height))
2919 switch (internalformat) {
2920 case GraphicsContext3D::DEPTH_COMPONENT16:
2921 case GraphicsContext3D::RGBA4:
2922 case GraphicsContext3D::RGB5_A1:
2923 case GraphicsContext3D::RGB565:
2924 case GraphicsContext3D::STENCIL_INDEX8:
2925 m_context->renderbufferStorage(target, internalformat, width, height);
2926 m_renderbufferBinding->setInternalFormat(internalformat);
2927 m_renderbufferBinding->setIsValid(true);
2928 m_renderbufferBinding->setSize(width, height);
2929 cleanupAfterGraphicsCall(false);
2931 case GraphicsContext3D::DEPTH_STENCIL:
2932 if (isDepthStencilSupported()) {
2933 m_context->renderbufferStorage(target, Extensions3D::DEPTH24_STENCIL8, width, height);
2934 cleanupAfterGraphicsCall(false);
2936 m_renderbufferBinding->setSize(width, height);
2937 m_renderbufferBinding->setIsValid(isDepthStencilSupported());
2938 m_renderbufferBinding->setInternalFormat(internalformat);
2941 m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
2945 void WebGLRenderingContext::sampleCoverage(GC3Dfloat value, GC3Dboolean invert)
2947 if (isContextLost())
2949 m_context->sampleCoverage(value, invert);
2950 cleanupAfterGraphicsCall(false);
2953 void WebGLRenderingContext::scissor(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height)
2955 if (isContextLost())
2957 if (!validateSize(width, height))
2959 m_context->scissor(x, y, width, height);
2960 cleanupAfterGraphicsCall(false);
2963 void WebGLRenderingContext::shaderSource(WebGLShader* shader, const String& string, ExceptionCode& ec)
2966 if (isContextLost() || !validateWebGLObject(shader))
2968 String stringWithoutComments = StripComments(string).result();
2969 if (!validateString(stringWithoutComments))
2971 shader->setSource(string);
2972 m_context->shaderSource(objectOrZero(shader), stringWithoutComments);
2973 cleanupAfterGraphicsCall(false);
2976 void WebGLRenderingContext::stencilFunc(GC3Denum func, GC3Dint ref, GC3Duint mask)
2978 if (isContextLost())
2980 if (!validateStencilFunc(func))
2982 m_stencilFuncRef = ref;
2983 m_stencilFuncRefBack = ref;
2984 m_stencilFuncMask = mask;
2985 m_stencilFuncMaskBack = mask;
2986 m_context->stencilFunc(func, ref, mask);
2987 cleanupAfterGraphicsCall(false);
2990 void WebGLRenderingContext::stencilFuncSeparate(GC3Denum face, GC3Denum func, GC3Dint ref, GC3Duint mask)
2992 if (isContextLost())
2994 if (!validateStencilFunc(func))
2997 case GraphicsContext3D::FRONT_AND_BACK:
2998 m_stencilFuncRef = ref;
2999 m_stencilFuncRefBack = ref;
3000 m_stencilFuncMask = mask;
3001 m_stencilFuncMaskBack = mask;
3003 case GraphicsContext3D::FRONT:
3004 m_stencilFuncRef = ref;
3005 m_stencilFuncMask = mask;
3007 case GraphicsContext3D::BACK:
3008 m_stencilFuncRefBack = ref;
3009 m_stencilFuncMaskBack = mask;
3012 m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
3015 m_context->stencilFuncSeparate(face, func, ref, mask);
3016 cleanupAfterGraphicsCall(false);
3019 void WebGLRenderingContext::stencilMask(GC3Duint mask)
3021 if (isContextLost())
3023 m_stencilMask = mask;
3024 m_stencilMaskBack = mask;
3025 m_context->stencilMask(mask);
3026 cleanupAfterGraphicsCall(false);
3029 void WebGLRenderingContext::stencilMaskSeparate(GC3Denum face, GC3Duint mask)
3031 if (isContextLost())
3034 case GraphicsContext3D::FRONT_AND_BACK:
3035 m_stencilMask = mask;
3036 m_stencilMaskBack = mask;
3038 case GraphicsContext3D::FRONT:
3039 m_stencilMask = mask;
3041 case GraphicsContext3D::BACK:
3042 m_stencilMaskBack = mask;
3045 m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
3048 m_context->stencilMaskSeparate(face, mask);
3049 cleanupAfterGraphicsCall(false);
3052 void WebGLRenderingContext::stencilOp(GC3Denum fail, GC3Denum zfail, GC3Denum zpass)
3054 if (isContextLost())
3056 m_context->stencilOp(fail, zfail, zpass);
3057 cleanupAfterGraphicsCall(false);
3060 void WebGLRenderingContext::stencilOpSeparate(GC3Denum face, GC3Denum fail, GC3Denum zfail, GC3Denum zpass)
3062 if (isContextLost())
3064 m_context->stencilOpSeparate(face, fail, zfail, zpass);
3065 cleanupAfterGraphicsCall(false);
3068 void WebGLRenderingContext::texImage2DBase(GC3Denum target, GC3Dint level, GC3Denum internalformat,
3069 GC3Dsizei width, GC3Dsizei height, GC3Dint border,
3070 GC3Denum format, GC3Denum type, void* pixels, ExceptionCode& ec)
3072 // FIXME: For now we ignore any errors returned
3074 if (!validateTexFuncParameters(target, level, internalformat, width, height, border, format, type))
3076 WebGLTexture* tex = validateTextureBinding(target, true);
3079 if (!isGLES2NPOTStrict()) {
3080 if (level && WebGLTexture::isNPOT(width, height)) {
3081 m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
3086 bool succeed = m_context->texImage2DResourceSafe(target, level, internalformat, width, height,
3087 border, format, type, m_unpackAlignment);
3091 m_context->texImage2D(target, level, internalformat, width, height,
3092 border, format, type, pixels);
3094 tex->setLevelInfo(target, level, internalformat, width, height, type);
3095 cleanupAfterGraphicsCall(false);
3098 void WebGLRenderingContext::texImage2DImpl(GC3Denum target, GC3Dint level, GC3Denum internalformat,
3099 GC3Denum format, GC3Denum type, Image* image,
3100 bool flipY, bool premultiplyAlpha, ExceptionCode& ec)
3103 Vector<uint8_t> data;
3104 if (!m_context->extractImageData(image, format, type, flipY, premultiplyAlpha, m_unpackColorspaceConversion == GraphicsContext3D::NONE, data)) {
3105 m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
3108 if (m_unpackAlignment != 1)
3109 m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, 1);
3110 texImage2DBase(target, level, internalformat, image->width(), image->height(), 0,
3111 format, type, data.data(), ec);
3112 if (m_unpackAlignment != 1)
3113 m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, m_unpackAlignment);
3116 void WebGLRenderingContext::texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat,
3117 GC3Dsizei width, GC3Dsizei height, GC3Dint border,
3118 GC3Denum format, GC3Denum type, ArrayBufferView* pixels, ExceptionCode& ec)
3120 if (isContextLost() || !validateTexFuncData(width, height, format, type, pixels))
3122 void* data = pixels ? pixels->baseAddress() : 0;
3123 Vector<uint8_t> tempData;
3124 bool changeUnpackAlignment = false;
3125 if (data && (m_unpackFlipY || m_unpackPremultiplyAlpha)) {
3126 if (!m_context->extractTextureData(width, height, format, type,
3128 m_unpackFlipY, m_unpackPremultiplyAlpha,
3132 data = tempData.data();
3133 changeUnpackAlignment = true;
3135 if (changeUnpackAlignment)
3136 m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, 1);
3137 texImage2DBase(target, level, internalformat, width, height, border,
3138 format, type, data, ec);
3139 if (changeUnpackAlignment)
3140 m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, m_unpackAlignment);
3143 void WebGLRenderingContext::texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat,
3144 GC3Denum format, GC3Denum type, ImageData* pixels, ExceptionCode& ec)
3147 if (isContextLost())
3149 Vector<uint8_t> data;
3150 if (!m_context->extractImageData(pixels, format, type, m_unpackFlipY, m_unpackPremultiplyAlpha, data)) {
3151 m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
3154 if (m_unpackAlignment != 1)
3155 m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, 1);
3156 texImage2DBase(target, level, internalformat, pixels->width(), pixels->height(), 0,
3157 format, type, data.data(), ec);
3158 if (m_unpackAlignment != 1)
3159 m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, m_unpackAlignment);
3162 void WebGLRenderingContext::texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat,
3163 GC3Denum format, GC3Denum type, HTMLImageElement* image, ExceptionCode& ec)
3166 if (isContextLost())
3168 if (!validateHTMLImageElement(image))
3170 if (wouldTaintOrigin(image)) {
3175 texImage2DImpl(target, level, internalformat, format, type, image->cachedImage()->image(),
3176 m_unpackFlipY, m_unpackPremultiplyAlpha, ec);
3179 void WebGLRenderingContext::texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat,
3180 GC3Denum format, GC3Denum type, HTMLCanvasElement* canvas, ExceptionCode& ec)
3183 if (isContextLost())
3185 if (!canvas || !canvas->buffer()) {
3186 m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
3189 if (wouldTaintOrigin(canvas)) {
3193 RefPtr<ImageData> imageData = canvas->getImageData();
3195 texImage2D(target, level, internalformat, format, type, imageData.get(), ec);
3197 texImage2DImpl(target, level, internalformat, format, type, canvas->copiedImage(),
3198 m_unpackFlipY, m_unpackPremultiplyAlpha, ec);
3202 PassRefPtr<Image> WebGLRenderingContext::videoFrameToImage(HTMLVideoElement* video, ExceptionCode& ec)
3204 if (!video || !video->videoWidth() || !video->videoHeight()) {
3205 m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
3208 IntSize size(video->videoWidth(), video->videoHeight());
3209 ImageBuffer* buf = m_videoCache.imageBuffer(size);
3211 m_context->synthesizeGLError(GraphicsContext3D::OUT_OF_MEMORY);
3214 if (wouldTaintOrigin(video)) {
3218 IntRect destRect(0, 0, size.width(), size.height());
3219 // FIXME: Turn this into a GPU-GPU texture copy instead of CPU readback.
3220 video->paintCurrentFrameInContext(buf->context(), destRect);
3221 return buf->copyImage(CopyBackingStore);
3224 void WebGLRenderingContext::texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat,
3225 GC3Denum format, GC3Denum type, HTMLVideoElement* video, ExceptionCode& ec)
3228 if (isContextLost())
3230 RefPtr<Image> image = videoFrameToImage(video, ec);
3233 texImage2DImpl(target, level, internalformat, format, type, image.get(), m_unpackFlipY, m_unpackPremultiplyAlpha, ec);
3237 void WebGLRenderingContext::texParameter(GC3Denum target, GC3Denum pname, GC3Dfloat paramf, GC3Dint parami, bool isFloat)
3239 if (isContextLost())
3241 WebGLTexture* tex = validateTextureBinding(target, false);
3245 case GraphicsContext3D::TEXTURE_MIN_FILTER:
3246 case GraphicsContext3D::TEXTURE_MAG_FILTER:
3248 case GraphicsContext3D::TEXTURE_WRAP_S:
3249 case GraphicsContext3D::TEXTURE_WRAP_T:
3250 if ((isFloat && paramf != GraphicsContext3D::CLAMP_TO_EDGE && paramf != GraphicsContext3D::MIRRORED_REPEAT && paramf != GraphicsContext3D::REPEAT)
3251 || (!isFloat && parami != GraphicsContext3D::CLAMP_TO_EDGE && parami != GraphicsContext3D::MIRRORED_REPEAT && parami != GraphicsContext3D::REPEAT)) {
3252 m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
3257 m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
3261 tex->setParameterf(pname, paramf);
3262 m_context->texParameterf(target, pname, paramf);
3264 tex->setParameteri(pname, parami);
3265 m_context->texParameteri(target, pname, parami);
3267 cleanupAfterGraphicsCall(false);
3270 void WebGLRenderingContext::texParameterf(GC3Denum target, GC3Denum pname, GC3Dfloat param)
3272 texParameter(target, pname, param, 0, true);
3275 void WebGLRenderingContext::texParameteri(GC3Denum target, GC3Denum pname, GC3Dint param)
3277 texParameter(target, pname, 0, param, false);
3280 void WebGLRenderingContext::texSubImage2DBase(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
3281 GC3Dsizei width, GC3Dsizei height,
3282 GC3Denum format, GC3Denum type, void* pixels, ExceptionCode& ec)
3284 // FIXME: For now we ignore any errors returned
3286 if (isContextLost())
3288 if (!validateTexFuncParameters(target, level, format, width, height, 0, format, type))
3290 if (!validateSize(xoffset, yoffset))
3292 WebGLTexture* tex = validateTextureBinding(target, true);
3295 if (xoffset + width > tex->getWidth(target, level) || yoffset + height > tex->getHeight(target, level)) {
3296 m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
3299 if (tex->getInternalFormat(target, level) != format || tex->getType(target, level) != type) {
3300 m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
3303 m_context->texSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels);
3304 cleanupAfterGraphicsCall(false);
3307 void WebGLRenderingContext::texSubImage2DImpl(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
3308 GC3Denum format, GC3Denum type,
3309 Image* image, bool flipY, bool premultiplyAlpha, ExceptionCode& ec)
3312 if (isContextLost())
3314 Vector<uint8_t> data;
3315 if (!m_context->extractImageData(image, format, type, flipY, premultiplyAlpha, m_unpackColorspaceConversion == GraphicsContext3D::NONE, data)) {
3316 m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
3319 texSubImage2DBase(target, level, xoffset, yoffset, image->width(), image->height(),
3320 format, type, data.data(), ec);
3323 void WebGLRenderingContext::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
3324 GC3Dsizei width, GC3Dsizei height,
3325 GC3Denum format, GC3Denum type, ArrayBufferView* pixels, ExceptionCode& ec)
3327 if (isContextLost() || !validateTexFuncData(width, height, format, type, pixels))
3329 void* data = pixels ? pixels->baseAddress() : 0;
3330 Vector<uint8_t> tempData;
3331 bool changeUnpackAlignment = false;
3332 if (data && (m_unpackFlipY || m_unpackPremultiplyAlpha)) {
3333 if (!m_context->extractTextureData(width, height, format, type,
3335 m_unpackFlipY, m_unpackPremultiplyAlpha,
3339 data = tempData.data();
3340 changeUnpackAlignment = true;
3342 if (changeUnpackAlignment)
3343 m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, 1);
3344 texSubImage2DBase(target, level, xoffset, yoffset, width, height, format, type, data, ec);
3345 if (changeUnpackAlignment)
3346 m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, m_unpackAlignment);
3349 void WebGLRenderingContext::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
3350 GC3Denum format, GC3Denum type, ImageData* pixels, ExceptionCode& ec)
3353 if (isContextLost())
3355 Vector<uint8_t> data;
3356 if (!m_context->extractImageData(pixels, format, type, m_unpackFlipY, m_unpackPremultiplyAlpha, data)) {
3357 m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
3360 texSubImage2DBase(target, level, xoffset, yoffset, pixels->width(), pixels->height(),
3361 format, type, data.data(), ec);
3364 void WebGLRenderingContext::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
3365 GC3Denum format, GC3Denum type, HTMLImageElement* image, ExceptionCode& ec)
3368 if (isContextLost())
3370 if (!validateHTMLImageElement(image))
3372 if (wouldTaintOrigin(image)) {
3376 texSubImage2DImpl(target, level, xoffset, yoffset, format, type, image->cachedImage()->image(),
3377 m_unpackFlipY, m_unpackPremultiplyAlpha, ec);
3380 void WebGLRenderingContext::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
3381 GC3Denum format, GC3Denum type, HTMLCanvasElement* canvas, ExceptionCode& ec)
3384 if (isContextLost())
3386 if (!canvas || !canvas->buffer()) {
3387 m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
3390 if (wouldTaintOrigin(canvas)) {
3394 RefPtr<ImageData> imageData = canvas->getImageData();
3396 texSubImage2D(target, level, xoffset, yoffset, format, type, imageData.get(), ec);
3398 texSubImage2DImpl(target, level, xoffset, yoffset, format, type, canvas->copiedImage(),
3399 m_unpackFlipY, m_unpackPremultiplyAlpha, ec);
3403 void WebGLRenderingContext::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
3404 GC3Denum format, GC3Denum type, HTMLVideoElement* video, ExceptionCode& ec)
3407 if (isContextLost())
3409 RefPtr<Image> image = videoFrameToImage(video, ec);
3412 texSubImage2DImpl(target, level, xoffset, yoffset, format, type, image.get(), m_unpackFlipY, m_unpackPremultiplyAlpha, ec);
3416 void WebGLRenderingContext::uniform1f(const WebGLUniformLocation* location, GC3Dfloat x, ExceptionCode& ec)
3419 if (isContextLost() || !location)
3422 if (location->program() != m_currentProgram) {
3423 m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
3427 m_context->uniform1f(location->location(), x);
3428 cleanupAfterGraphicsCall(false);
3431 void WebGLRenderingContext::uniform1fv(const WebGLUniformLocation* location, Float32Array* v, ExceptionCode& ec)
3434 if (isContextLost() || !validateUniformParameters(location, v, 1))
3437 m_context->uniform1fv(location->location(), v->data(), v->length());
3438 cleanupAfterGraphicsCall(false);
3441 void WebGLRenderingContext::uniform1fv(const WebGLUniformLocation* location, GC3Dfloat* v, GC3Dsizei size, ExceptionCode& ec)
3444 if (isContextLost() || !validateUniformParameters(location, v, size, 1))
3447 m_context->uniform1fv(location->location(), v, size);
3448 cleanupAfterGraphicsCall(false);
3451 void WebGLRenderingContext::uniform1i(const WebGLUniformLocation* location, GC3Dint x, ExceptionCode& ec)
3454 if (isContextLost() || !location)
3457 if (location->program() != m_currentProgram) {
3458 m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
3462 m_context->uniform1i(location->location(), x);
3463 cleanupAfterGraphicsCall(false);
3466 void WebGLRenderingContext::uniform1iv(const WebGLUniformLocation* location, Int32Array* v, ExceptionCode& ec)
3469 if (isContextLost() || !validateUniformParameters(location, v, 1))
3472 m_context->uniform1iv(location->location(), v->data(), v->length());
3473 cleanupAfterGraphicsCall(false);
3476 void WebGLRenderingContext::uniform1iv(const WebGLUniformLocation* location, GC3Dint* v, GC3Dsizei size, ExceptionCode& ec)
3479 if (isContextLost() || !validateUniformParameters(location, v, size, 1))
3482 m_context->uniform1iv(location->location(), v, size);
3483 cleanupAfterGraphicsCall(false);
3486 void WebGLRenderingContext::uniform2f(const WebGLUniformLocation* location, GC3Dfloat x, GC3Dfloat y, ExceptionCode& ec)
3489 if (isContextLost() || !location)
3492 if (location->program() != m_currentProgram) {
3493 m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
3497 m_context->uniform2f(location->location(), x, y);
3498 cleanupAfterGraphicsCall(false);
3501 void WebGLRenderingContext::uniform2fv(const WebGLUniformLocation* location, Float32Array* v, ExceptionCode& ec)
3504 if (isContextLost() || !validateUniformParameters(location, v, 2))
3507 m_context->uniform2fv(location->location(), v->data(), v->length() / 2);
3508 cleanupAfterGraphicsCall(false);
3511 void WebGLRenderingContext::uniform2fv(const WebGLUniformLocation* location, GC3Dfloat* v, GC3Dsizei size, ExceptionCode& ec)
3514 if (isContextLost() || !validateUniformParameters(location, v, size, 2))
3517 m_context->uniform2fv(location->location(), v, size / 2);
3518 cleanupAfterGraphicsCall(false);
3521 void WebGLRenderingContext::uniform2i(const WebGLUniformLocation* location, GC3Dint x, GC3Dint y, ExceptionCode& ec)
3524 if (isContextLost() || !location)
3527 if (location->program() != m_currentProgram) {
3528 m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
3532 m_context->uniform2i(location->location(), x, y);
3533 cleanupAfterGraphicsCall(false);
3536 void WebGLRenderingContext::uniform2iv(const WebGLUniformLocation* location, Int32Array* v, ExceptionCode& ec)
3539 if (isContextLost() || !validateUniformParameters(location, v, 2))
3542 m_context->uniform2iv(location->location(), v->data(), v->length() / 2);
3543 cleanupAfterGraphicsCall(false);
3546 void WebGLRenderingContext::uniform2iv(const WebGLUniformLocation* location, GC3Dint* v, GC3Dsizei size, ExceptionCode& ec)
3549 if (isContextLost() || !validateUniformParameters(location, v, size, 2))
3552 m_context->uniform2iv(location->location(), v, size / 2);
3553 cleanupAfterGraphicsCall(false);
3556 void WebGLRenderingContext::uniform3f(const WebGLUniformLocation* location, GC3Dfloat x, GC3Dfloat y, GC3Dfloat z, ExceptionCode& ec)
3559 if (isContextLost() || !location)
3562 if (location->program() != m_currentProgram) {
3563 m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
3567 m_context->uniform3f(location->location(), x, y, z);
3568 cleanupAfterGraphicsCall(false);
3571 void WebGLRenderingContext::uniform3fv(const WebGLUniformLocation* location, Float32Array* v, ExceptionCode& ec)
3574 if (isContextLost() || !validateUniformParameters(location, v, 3))
3577 m_context->uniform3fv(location->location(), v->data(), v->length() / 3);
3578 cleanupAfterGraphicsCall(false);
3581 void WebGLRenderingContext::uniform3fv(const WebGLUniformLocation* location, GC3Dfloat* v, GC3Dsizei size, ExceptionCode& ec)
3584 if (isContextLost() || !validateUniformParameters(location, v, size, 3))
3587 m_context->uniform3fv(location->location(), v, size / 3);
3588 cleanupAfterGraphicsCall(false);
3591 void WebGLRenderingContext::uniform3i(const WebGLUniformLocation* location, GC3Dint x, GC3Dint y, GC3Dint z, ExceptionCode& ec)
3594 if (isContextLost() || !location)
3597 if (location->program() != m_currentProgram) {
3598 m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
3602 m_context->uniform3i(location->location(), x, y, z);
3603 cleanupAfterGraphicsCall(false);
3606 void WebGLRenderingContext::uniform3iv(const WebGLUniformLocation* location, Int32Array* v, ExceptionCode& ec)
3609 if (isContextLost() || !validateUniformParameters(location, v, 3))
3612 m_context->uniform3iv(location->location(), v->data(), v->length() / 3);
3613 cleanupAfterGraphicsCall(false);
3616 void WebGLRenderingContext::uniform3iv(const WebGLUniformLocation* location, GC3Dint* v, GC3Dsizei size, ExceptionCode& ec)
3619 if (isContextLost() || !validateUniformParameters(location, v, size, 3))
3622 m_context->uniform3iv(location->location(), v, size / 3);
3623 cleanupAfterGraphicsCall(false);
3626 void WebGLRenderingContext::uniform4f(const WebGLUniformLocation* location, GC3Dfloat x, GC3Dfloat y, GC3Dfloat z, GC3Dfloat w, ExceptionCode& ec)
3629 if (isContextLost() || !location)
3632 if (location->program() != m_currentProgram) {
3633 m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
3637 m_context->uniform4f(location->location(), x, y, z, w);
3638 cleanupAfterGraphicsCall(false);
3641 void WebGLRenderingContext::uniform4fv(const WebGLUniformLocation* location, Float32Array* v, ExceptionCode& ec)
3644 if (isContextLost() || !validateUniformParameters(location, v, 4))
3647 m_context->uniform4fv(location->location(), v->data(), v->length() / 4);
3648 cleanupAfterGraphicsCall(false);
3651 void WebGLRenderingContext::uniform4fv(const WebGLUniformLocation* location, GC3Dfloat* v, GC3Dsizei size, ExceptionCode& ec)
3654 if (isContextLost() || !validateUniformParameters(location, v, size, 4))
3657 m_context->uniform4fv(location->location(), v, size / 4);
3658 cleanupAfterGraphicsCall(false);
3661 void WebGLRenderingContext::uniform4i(const WebGLUniformLocation* location, GC3Dint x, GC3Dint y, GC3Dint z, GC3Dint w, ExceptionCode& ec)
3664 if (isContextLost() || !location)
3667 if (location->program() != m_currentProgram) {
3668 m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
3672 m_context->uniform4i(location->location(), x, y, z, w);
3673 cleanupAfterGraphicsCall(false);
3676 void WebGLRenderingContext::uniform4iv(const WebGLUniformLocation* location, Int32Array* v, ExceptionCode& ec)
3679 if (isContextLost() || !validateUniformParameters(location, v, 4))
3682 m_context->uniform4iv(location->location(), v->data(), v->length() / 4);
3683 cleanupAfterGraphicsCall(false);
3686 void WebGLRenderingContext::uniform4iv(const WebGLUniformLocation* location, GC3Dint* v, GC3Dsizei size, ExceptionCode& ec)
3689 if (isContextLost() || !validateUniformParameters(location, v, size, 4))
3692 m_context->uniform4iv(location->location(), v, size / 4);
3693 cleanupAfterGraphicsCall(false);
3696 void WebGLRenderingContext::uniformMatrix2fv(const WebGLUniformLocation* location, GC3Dboolean transpose, Float32Array* v, ExceptionCode& ec)
3699 if (isContextLost() || !validateUniformMatrixParameters(location, transpose, v, 4))
3701 m_context->uniformMatrix2fv(location->location(), transpose, v->data(), v->length() / 4);
3702 cleanupAfterGraphicsCall(false);
3705 void WebGLRenderingContext::uniformMatrix2fv(const WebGLUniformLocation* location, GC3Dboolean transpose, GC3Dfloat* v, GC3Dsizei size, ExceptionCode& ec)
3708 if (isContextLost() || !validateUniformMatrixParameters(location, transpose, v, size, 4))
3710 m_context->uniformMatrix2fv(location->location(), transpose, v, size / 4);
3711 cleanupAfterGraphicsCall(false);
3714 void WebGLRenderingContext::uniformMatrix3fv(const WebGLUniformLocation* location, GC3Dboolean transpose, Float32Array* v, ExceptionCode& ec)
3717 if (isContextLost() || !validateUniformMatrixParameters(location, transpose, v, 9))
3719 m_context->uniformMatrix3fv(location->location(), transpose, v->data(), v->length() / 9);
3720 cleanupAfterGraphicsCall(false);
3723 void WebGLRenderingContext::uniformMatrix3fv(const WebGLUniformLocation* location, GC3Dboolean transpose, GC3Dfloat* v, GC3Dsizei size, ExceptionCode& ec)
3726 if (isContextLost() || !validateUniformMatrixParameters(location, transpose, v, size, 9))
3728 m_context->uniformMatrix3fv(location->location(), transpose, v, size / 9);
3729 cleanupAfterGraphicsCall(false);
3732 void WebGLRenderingContext::uniformMatrix4fv(const WebGLUniformLocation* location, GC3Dboolean transpose, Float32Array* v, ExceptionCode& ec)
3735 if (isContextLost() || !validateUniformMatrixParameters(location, transpose, v, 16))
3737 m_context->uniformMatrix4fv(location->location(), transpose, v->data(), v->length() / 16);
3738 cleanupAfterGraphicsCall(false);
3741 void WebGLRenderingContext::uniformMatrix4fv(const WebGLUniformLocation* location, GC3Dboolean transpose, GC3Dfloat* v, GC3Dsizei size, ExceptionCode& ec)
3744 if (isContextLost() || !validateUniformMatrixParameters(location, transpose, v, size, 16))
3746 m_context->uniformMatrix4fv(location->location(), transpose, v, size / 16);
3747 cleanupAfterGraphicsCall(false);
3750 void WebGLRenderingContext::useProgram(WebGLProgram* program, ExceptionCode& ec)
3754 if (!checkObjectToBeBound(program, deleted))
3758 if (program && !program->getLinkStatus()) {
3759 m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
3760 cleanupAfterGraphicsCall(false);
3763 if (m_currentProgram != program) {
3764 if (m_currentProgram)
3765 m_currentProgram->onDetached();
3766 m_currentProgram = program;
3767 m_context->useProgram(objectOrZero(program));
3769 program->onAttached();
3771 cleanupAfterGraphicsCall(false);
3774 void WebGLRenderingContext::validateProgram(WebGLProgram* program, ExceptionCode& ec)
3777 if (isContextLost() || !validateWebGLObject(program))
3779 m_context->validateProgram(objectOrZero(program));
3780 cleanupAfterGraphicsCall(false);
3783 void WebGLRenderingContext::vertexAttrib1f(GC3Duint index, GC3Dfloat v0)
3785 vertexAttribfImpl(index, 1, v0, 0.0f, 0.0f, 1.0f);
3788 void WebGLRenderingContext::vertexAttrib1fv(GC3Duint index, Float32Array* v)
3790 vertexAttribfvImpl(index, v, 1);
3793 void WebGLRenderingContext::vertexAttrib1fv(GC3Duint index, GC3Dfloat* v, GC3Dsizei size)
3795 vertexAttribfvImpl(index, v, size, 1);
3798 void WebGLRenderingContext::vertexAttrib2f(GC3Duint index, GC3Dfloat v0, GC3Dfloat v1)
3800 vertexAttribfImpl(index, 2, v0, v1, 0.0f, 1.0f);
3803 void WebGLRenderingContext::vertexAttrib2fv(GC3Duint index, Float32Array* v)
3805 vertexAttribfvImpl(index, v, 2);
3808 void WebGLRenderingContext::vertexAttrib2fv(GC3Duint index, GC3Dfloat* v, GC3Dsizei size)
3810 vertexAttribfvImpl(index, v, size, 2);
3813 void WebGLRenderingContext::vertexAttrib3f(GC3Duint index, GC3Dfloat v0, GC3Dfloat v1, GC3Dfloat v2)
3815 vertexAttribfImpl(index, 3, v0, v1, v2, 1.0f);
3818 void WebGLRenderingContext::vertexAttrib3fv(GC3Duint index, Float32Array* v)
3820 vertexAttribfvImpl(index, v, 3);
3823 void WebGLRenderingContext::vertexAttrib3fv(GC3Duint index, GC3Dfloat* v, GC3Dsizei size)
3825 vertexAttribfvImpl(index, v, size, 3);
3828 void WebGLRenderingContext::vertexAttrib4f(GC3Duint index, GC3Dfloat v0, GC3Dfloat v1, GC3Dfloat v2, GC3Dfloat v3)
3830 vertexAttribfImpl(index, 4, v0, v1, v2, v3);
3833 void WebGLRenderingContext::vertexAttrib4fv(GC3Duint index, Float32Array* v)
3835 vertexAttribfvImpl(index, v, 4);
3838 void WebGLRenderingContext::vertexAttrib4fv(GC3Duint index, GC3Dfloat* v, GC3Dsizei size)
3840 vertexAttribfvImpl(index, v, size, 4);
3843 void WebGLRenderingContext::vertexAttribPointer(GC3Duint index, GC3Dint size, GC3Denum type, GC3Dboolean normalized, GC3Dsizei stride, GC3Dintptr offset, ExceptionCode& ec)
3846 if (isContextLost())
3849 case GraphicsContext3D::BYTE:
3850 case GraphicsContext3D::UNSIGNED_BYTE:
3851 case GraphicsContext3D::SHORT:
3852 case GraphicsContext3D::UNSIGNED_SHORT:
3853 case GraphicsContext3D::FLOAT:
3856 m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
3859 if (index >= m_maxVertexAttribs) {
3860 m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
3863 if (size < 1 || size > 4 || stride < 0 || stride > 255 || offset < 0) {
3864 m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
3867 if (!m_boundArrayBuffer) {
3868 m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
3871 // Determine the number of elements the bound buffer can hold, given the offset, size, type and stride
3872 unsigned int typeSize = sizeInBytes(type);
3874 m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
3877 if ((stride % typeSize) || (offset % typeSize)) {
3878 m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
3881 GC3Dsizei bytesPerElement = size * typeSize;
3883 GC3Dsizei validatedStride = stride ? stride : bytesPerElement;
3885 WebGLVertexArrayObjectOES::VertexAttribState& state = m_boundVertexArrayObject->getVertexAttribState(index);
3886 state.bufferBinding = m_boundArrayBuffer;
3887 state.bytesPerElement = bytesPerElement;
3890 state.normalized = normalized;
3891 state.stride = validatedStride;
3892 state.originalStride = stride;
3893 state.offset = offset;
3894 m_context->vertexAttribPointer(index, size, type, normalized, stride, offset);
3895 cleanupAfterGraphicsCall(false);
3898 void WebGLRenderingContext::viewport(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height)
3900 if (isContextLost())
3902 if (!validateSize(width, height))
3904 m_context->viewport(x, y, width, height);
3905 cleanupAfterGraphicsCall(false);
3908 void WebGLRenderingContext::forceLostContext(WebGLRenderingContext::LostContextMode mode)
3910 if (isContextLost()) {
3911 m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
3917 if (mode == RealLostContext)
3918 m_restoreTimer.startOneShot(0);
3921 void WebGLRenderingContext::forceRestoreContext()
3923 if (!isContextLost()) {
3924 m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
3928 maybeRestoreContext(SyntheticLostContext);
3931 void WebGLRenderingContext::removeObject(WebGLObject* object)
3933 m_canvasObjects.remove(object);
3936 void WebGLRenderingContext::addObject(WebGLObject* object)
3938 ASSERT(!isContextLost());
3939 removeObject(object);
3940 m_canvasObjects.add(object);
3943 void WebGLRenderingContext::detachAndRemoveAllObjects()
3945 while (m_canvasObjects.size() > 0) {
3946 HashSet<WebGLObject*>::iterator it = m_canvasObjects.begin();
3947 (*it)->detachContext();
3951 WebGLGetInfo WebGLRenderingContext::getBooleanParameter(GC3Denum pname)
3953 GC3Dboolean value = 0;
3954 m_context->getBooleanv(pname, &value);
3955 return WebGLGetInfo(static_cast<bool>(value));
3958 WebGLGetInfo WebGLRenderingContext::getBooleanArrayParameter(GC3Denum pname)
3960 if (pname != GraphicsContext3D::COLOR_WRITEMASK) {
3962 return WebGLGetInfo(0, 0);
3964 GC3Dboolean value[4] = {0};
3965 m_context->getBooleanv(pname, value);
3967 for (int ii = 0; ii < 4; ++ii)
3968 boolValue[ii] = static_cast<bool>(value[ii]);
3969 return WebGLGetInfo(boolValue, 4);
3972 WebGLGetInfo WebGLRenderingContext::getFloatParameter(GC3Denum pname)
3974 GC3Dfloat value = 0;
3975 m_context->getFloatv(pname, &value);
3976 return WebGLGetInfo(value);
3979 WebGLGetInfo WebGLRenderingContext::getIntParameter(GC3Denum pname)
3982 m_context->getIntegerv(pname, &value);
3983 return WebGLGetInfo(value);
3986 WebGLGetInfo WebGLRenderingContext::getUnsignedIntParameter(GC3Denum pname)
3989 m_context->getIntegerv(pname, &value);
3990 return WebGLGetInfo(static_cast<unsigned int>(value));
3993 WebGLGetInfo WebGLRenderingContext::getWebGLFloatArrayParameter(GC3Denum pname)
3995 GC3Dfloat value[4] = {0};
3996 m_context->getFloatv(pname, value);
3997 unsigned length = 0;
3999 case GraphicsContext3D::ALIASED_POINT_SIZE_RANGE:
4000 case GraphicsContext3D::ALIASED_LINE_WIDTH_RANGE:
4001 case GraphicsContext3D::DEPTH_RANGE:
4004 case GraphicsContext3D::BLEND_COLOR:
4005 case GraphicsContext3D::COLOR_CLEAR_VALUE:
4011 return WebGLGetInfo(Float32Array::create(value, length));
4014 WebGLGetInfo WebGLRenderingContext::getWebGLIntArrayParameter(GC3Denum pname)
4016 GC3Dint value[4] = {0};
4017 m_context->getIntegerv(pname, value);
4018 unsigned length = 0;
4020 case GraphicsContext3D::MAX_VIEWPORT_DIMS:
4023 case GraphicsContext3D::SCISSOR_BOX:
4024 case GraphicsContext3D::VIEWPORT:
4030 return WebGLGetInfo(Int32Array::create(value, length));
4033 void WebGLRenderingContext::handleNPOTTextures(bool prepareToDraw)
4035 bool resetActiveUnit = false;
4036 for (unsigned ii = 0; ii < m_textureUnits.size(); ++ii) {
4037 if ((m_textureUnits[ii].m_texture2DBinding && m_textureUnits[ii].m_texture2DBinding->needToUseBlackTexture())
4038 || (m_textureUnits[ii].m_textureCubeMapBinding && m_textureUnits[ii].m_textureCubeMapBinding->needToUseBlackTexture())) {
4039 if (ii != m_activeTextureUnit) {
4040 m_context->activeTexture(ii);
4041 resetActiveUnit = true;
4042 } else if (resetActiveUnit) {
4043 m_context->activeTexture(ii);
4044 resetActiveUnit = false;
4046 WebGLTexture* tex2D;
4047 WebGLTexture* texCubeMap;
4048 if (prepareToDraw) {
4049 tex2D = m_blackTexture2D.get();
4050 texCubeMap = m_blackTextureCubeMap.get();
4052 tex2D = m_textureUnits[ii].m_texture2DBinding.get();
4053 texCubeMap = m_textureUnits[ii].m_textureCubeMapBinding.get();
4055 if (m_textureUnits[ii].m_texture2DBinding && m_textureUnits[ii].m_texture2DBinding->needToUseBlackTexture())
4056 m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, objectOrZero(tex2D));
4057 if (m_textureUnits[ii].m_textureCubeMapBinding && m_textureUnits[ii].m_textureCubeMapBinding->needToUseBlackTexture())
4058 m_context->bindTexture(GraphicsContext3D::TEXTURE_CUBE_MAP, objectOrZero(texCubeMap));
4061 if (resetActiveUnit)
4062 m_context->activeTexture(m_activeTextureUnit);
4065 void WebGLRenderingContext::createFallbackBlackTextures1x1()
4067 unsigned char black[] = {0, 0, 0, 255};
4068 m_blackTexture2D = createTexture();
4069 m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_blackTexture2D->object());
4070 m_context->texImage2D(GraphicsContext3D::TEXTURE_2D, 0, GraphicsContext3D::RGBA, 1, 1,
4071 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, black);
4072 m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, 0);
4073 m_blackTextureCubeMap = createTexture();
4074 m_context->bindTexture(GraphicsContext3D::TEXTURE_CUBE_MAP, m_blackTextureCubeMap->object());
4075 m_context->texImage2D(GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_X, 0, GraphicsContext3D::RGBA, 1, 1,
4076 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, black);
4077 m_context->texImage2D(GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GraphicsContext3D::RGBA, 1, 1,
4078 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, black);
4079 m_context->texImage2D(GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GraphicsContext3D::RGBA, 1, 1,
4080 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, black);
4081 m_context->texImage2D(GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GraphicsContext3D::RGBA, 1, 1,
4082 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, black);
4083 m_context->texImage2D(GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GraphicsContext3D::RGBA, 1, 1,
4084 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, black);
4085 m_context->texImage2D(GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GraphicsContext3D::RGBA, 1, 1,
4086 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, black);
4087 m_context->bindTexture(GraphicsContext3D::TEXTURE_CUBE_MAP, 0);
4090 bool WebGLRenderingContext::isTexInternalFormatColorBufferCombinationValid(GC3Denum texInternalFormat,
4091 GC3Denum colorBufferFormat)
4093 switch (colorBufferFormat) {
4094 case GraphicsContext3D::ALPHA:
4095 if (texInternalFormat == GraphicsContext3D::ALPHA)
4098 case GraphicsContext3D::RGB:
4099 if (texInternalFormat == GraphicsContext3D::LUMINANCE
4100 || texInternalFormat == GraphicsContext3D::RGB)
4103 case GraphicsContext3D::RGBA:
4109 GC3Denum WebGLRenderingContext::getBoundFramebufferColorFormat()
4111 if (m_framebufferBinding && m_framebufferBinding->object())
4112 return m_framebufferBinding->getColorBufferFormat();
4113 if (m_attributes.alpha)
4114 return GraphicsContext3D::RGBA;
4115 return GraphicsContext3D::RGB;
4118 int WebGLRenderingContext::getBoundFramebufferWidth()
4120 if (m_framebufferBinding && m_framebufferBinding->object())
4121 return m_framebufferBinding->getWidth();
4122 return m_context->getInternalFramebufferSize().width();
4125 int WebGLRenderingContext::getBoundFramebufferHeight()
4127 if (m_framebufferBinding && m_framebufferBinding->object())
4128 return m_framebufferBinding->getHeight();
4129 return m_context->getInternalFramebufferSize().height();
4132 WebGLTexture* WebGLRenderingContext::validateTextureBinding(GC3Denum target, bool useSixEnumsForCubeMap)
4134 WebGLTexture* tex = 0;
4136 case GraphicsContext3D::TEXTURE_2D:
4137 tex = m_textureUnits[m_activeTextureUnit].m_texture2DBinding.get();
4139 case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_X:
4140 case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_X:
4141 case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Y:
4142 case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Y:
4143 case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Z:
4144 case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Z:
4145 if (!useSixEnumsForCubeMap) {
4146 m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
4149 tex = m_textureUnits[m_activeTextureUnit].m_textureCubeMapBinding.get();
4151 case GraphicsContext3D::TEXTURE_CUBE_MAP:
4152 if (useSixEnumsForCubeMap) {
4153 m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
4156 tex = m_textureUnits[m_activeTextureUnit].m_textureCubeMapBinding.get();
4159 m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
4163 m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
4167 bool WebGLRenderingContext::validateSize(GC3Dint x, GC3Dint y)
4169 if (x < 0 || y < 0) {
4170 m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
4176 bool WebGLRenderingContext::validateString(const String& string)
4178 for (size_t i = 0; i < string.length(); ++i) {
4179 if (!validateCharacter(string[i])) {
4180 m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
4187 bool WebGLRenderingContext::validateTexFuncFormatAndType(GC3Denum format, GC3Denum type)
4190 case GraphicsContext3D::ALPHA:
4191 case GraphicsContext3D::LUMINANCE:
4192 case GraphicsContext3D::LUMINANCE_ALPHA:
4193 case GraphicsContext3D::RGB:
4194 case GraphicsContext3D::RGBA:
4197 m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
4202 case GraphicsContext3D::UNSIGNED_BYTE:
4203 case GraphicsContext3D::UNSIGNED_SHORT_5_6_5:
4204 case GraphicsContext3D::UNSIGNED_SHORT_4_4_4_4:
4205 case GraphicsContext3D::UNSIGNED_SHORT_5_5_5_1:
4207 case GraphicsContext3D::FLOAT:
4208 if (m_oesTextureFloat)
4210 m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
4213 m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
4217 // Verify that the combination of format and type is supported.
4219 case GraphicsContext3D::ALPHA:
4220 case GraphicsContext3D::LUMINANCE:
4221 case GraphicsContext3D::LUMINANCE_ALPHA:
4222 if (type != GraphicsContext3D::UNSIGNED_BYTE
4223 && type != GraphicsContext3D::FLOAT) {
4224 m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
4228 case GraphicsContext3D::RGB:
4229 if (type != GraphicsContext3D::UNSIGNED_BYTE
4230 && type != GraphicsContext3D::UNSIGNED_SHORT_5_6_5
4231 && type != GraphicsContext3D::FLOAT) {
4232 m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
4236 case GraphicsContext3D::RGBA:
4237 if (type != GraphicsContext3D::UNSIGNED_BYTE
4238 && type != GraphicsContext3D::UNSIGNED_SHORT_4_4_4_4
4239 && type != GraphicsContext3D::UNSIGNED_SHORT_5_5_5_1
4240 && type != GraphicsContext3D::FLOAT) {
4241 m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
4246 ASSERT_NOT_REACHED();
4252 bool WebGLRenderingContext::validateTexFuncLevel(GC3Denum target, GC3Dint level)
4255 m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
4259 case GraphicsContext3D::TEXTURE_2D:
4260 if (level > m_maxTextureLevel) {
4261 m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
4265 case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_X:
4266 case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_X:
4267 case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Y:
4268 case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Y:
4269 case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Z:
4270 case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Z:
4271 if (level > m_maxCubeMapTextureLevel) {
4272 m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
4277 // This function only checks if level is legal, so we return true and don't
4278 // generate INVALID_ENUM if target is illegal.
4282 bool WebGLRenderingContext::validateTexFuncParameters(GC3Denum target, GC3Dint level,
4283 GC3Denum internalformat,
4284 GC3Dsizei width, GC3Dsizei height, GC3Dint border,
4285 GC3Denum format, GC3Denum type)
4287 // We absolutely have to validate the format and type combination.
4288 // The texImage2D entry points taking HTMLImage, etc. will produce
4289 // temporary data based on this combination, so it must be legal.
4290 if (!validateTexFuncFormatAndType(format, type) || !validateTexFuncLevel(target, level))
4293 if (width < 0 || height < 0) {
4294 m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
4299 case GraphicsContext3D::TEXTURE_2D:
4300 if (width > m_maxTextureSize || height > m_maxTextureSize) {
4301 m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
4305 case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_X:
4306 case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_X:
4307 case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Y:
4308 case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Y:
4309 case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Z:
4310 case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Z:
4311 if (width != height || width > m_maxCubeMapTextureSize) {
4312 m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
4317 m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
4321 if (format != internalformat) {
4322 m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
4327 m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
4334 bool WebGLRenderingContext::validateTexFuncData(GC3Dsizei width, GC3Dsizei height,
4335 GC3Denum format, GC3Denum type,
4336 ArrayBufferView* pixels)
4341 if (!validateTexFuncFormatAndType(format, type))
4345 case GraphicsContext3D::UNSIGNED_BYTE:
4346 if (!pixels->isUnsignedByteArray()) {
4347 m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
4351 case GraphicsContext3D::UNSIGNED_SHORT_5_6_5:
4352 case GraphicsContext3D::UNSIGNED_SHORT_4_4_4_4:
4353 case GraphicsContext3D::UNSIGNED_SHORT_5_5_5_1:
4354 if (!pixels->isUnsignedShortArray()) {
4355 m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
4359 case GraphicsContext3D::FLOAT: // OES_texture_float
4360 if (!pixels->isFloatArray()) {
4361 m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
4366 ASSERT_NOT_REACHED();
4369 unsigned int totalBytesRequired;
4370 GC3Denum error = m_context->computeImageSizeInBytes(format, type, width, height, m_unpackAlignment, &totalBytesRequired, 0);
4371 if (error != GraphicsContext3D::NO_ERROR) {
4372 m_context->synthesizeGLError(error);
4375 if (pixels->byteLength() < totalBytesRequired) {
4376 m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
4382 bool WebGLRenderingContext::validateDrawMode(GC3Denum mode)
4385 case GraphicsContext3D::POINTS:
4386 case GraphicsContext3D::LINE_STRIP:
4387 case GraphicsContext3D::LINE_LOOP:
4388 case GraphicsContext3D::LINES:
4389 case GraphicsContext3D::TRIANGLE_STRIP:
4390 case GraphicsContext3D::TRIANGLE_FAN:
4391 case GraphicsContext3D::TRIANGLES:
4394 m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
4399 bool WebGLRenderingContext::validateStencilSettings()
4401 if (m_stencilMask != m_stencilMaskBack || m_stencilFuncRef != m_stencilFuncRefBack || m_stencilFuncMask != m_stencilFuncMaskBack) {
4402 m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
4408 bool WebGLRenderingContext::validateStencilFunc(GC3Denum func)
4411 case GraphicsContext3D::NEVER:
4412 case GraphicsContext3D::LESS:
4413 case GraphicsContext3D::LEQUAL:
4414 case GraphicsContext3D::GREATER:
4415 case GraphicsContext3D::GEQUAL:
4416 case GraphicsContext3D::EQUAL:
4417 case GraphicsContext3D::NOTEQUAL:
4418 case GraphicsContext3D::ALWAYS:
4421 m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
4426 void WebGLRenderingContext::printWarningToConsole(const String& message)
4428 canvas()->document()->frame()->domWindow()->console()->addMessage(HTMLMessageSource, LogMessageType, WarningMessageLevel,
4429 message, 0, canvas()->document()->url().string());
4432 bool WebGLRenderingContext::validateFramebufferFuncParameters(GC3Denum target, GC3Denum attachment)
4434 if (target != GraphicsContext3D::FRAMEBUFFER) {
4435 m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
4438 switch (attachment) {
4439 case GraphicsContext3D::COLOR_ATTACHMENT0:
4440 case GraphicsContext3D::DEPTH_ATTACHMENT:
4441 case GraphicsContext3D::STENCIL_ATTACHMENT:
4442 case GraphicsContext3D::DEPTH_STENCIL_ATTACHMENT:
4445 m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
4451 bool WebGLRenderingContext::validateBlendEquation(GC3Denum mode)
4454 case GraphicsContext3D::FUNC_ADD:
4455 case GraphicsContext3D::FUNC_SUBTRACT:
4456 case GraphicsContext3D::FUNC_REVERSE_SUBTRACT:
4459 m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
4464 bool WebGLRenderingContext::validateBlendFuncFactors(GC3Denum src, GC3Denum dst)
4466 if (((src == GraphicsContext3D::CONSTANT_COLOR || src == GraphicsContext3D::ONE_MINUS_CONSTANT_COLOR)
4467 && (dst == GraphicsContext3D::CONSTANT_ALPHA || dst == GraphicsContext3D::ONE_MINUS_CONSTANT_ALPHA))
4468 || ((dst == GraphicsContext3D::CONSTANT_COLOR || dst == GraphicsContext3D::ONE_MINUS_CONSTANT_COLOR)
4469 && (src == GraphicsContext3D::CONSTANT_ALPHA || src == GraphicsContext3D::ONE_MINUS_CONSTANT_ALPHA))) {
4470 m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
4476 bool WebGLRenderingContext::validateCapability(GC3Denum cap)
4479 case GraphicsContext3D::BLEND:
4480 case GraphicsContext3D::CULL_FACE:
4481 case GraphicsContext3D::DEPTH_TEST:
4482 case GraphicsContext3D::DITHER:
4483 case GraphicsContext3D::POLYGON_OFFSET_FILL:
4484 case GraphicsContext3D::SAMPLE_ALPHA_TO_COVERAGE:
4485 case GraphicsContext3D::SAMPLE_COVERAGE:
4486 case GraphicsContext3D::SCISSOR_TEST:
4487 case GraphicsContext3D::STENCIL_TEST:
4490 m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
4495 bool WebGLRenderingContext::validateUniformParameters(const WebGLUniformLocation* location, Float32Array* v, GC3Dsizei requiredMinSize)
4498 m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
4501 return validateUniformMatrixParameters(location, false, v->data(), v->length(), requiredMinSize);
4504 bool WebGLRenderingContext::validateUniformParameters(const WebGLUniformLocation* location, Int32Array* v, GC3Dsizei requiredMinSize)
4507 m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
4510 return validateUniformMatrixParameters(location, false, v->data(), v->length(), requiredMinSize);
4513 bool WebGLRenderingContext::validateUniformParameters(const WebGLUniformLocation* location, void* v, GC3Dsizei size, GC3Dsizei requiredMinSize)
4515 return validateUniformMatrixParameters(location, false, v, size, requiredMinSize);
4518 bool WebGLRenderingContext::validateUniformMatrixParameters(const WebGLUniformLocation* location, GC3Dboolean transpose, Float32Array* v, GC3Dsizei requiredMinSize)
4521 m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
4524 return validateUniformMatrixParameters(location, transpose, v->data(), v->length(), requiredMinSize);
4527 bool WebGLRenderingContext::validateUniformMatrixParameters(const WebGLUniformLocation* location, GC3Dboolean transpose, void* v, GC3Dsizei size, GC3Dsizei requiredMinSize)
4531 if (location->program() != m_currentProgram) {
4532 m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
4536 m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
4540 m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
4543 if (size < requiredMinSize || (size % requiredMinSize)) {
4544 m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
4550 WebGLBuffer* WebGLRenderingContext::validateBufferDataParameters(GC3Denum target, GC3Denum usage)
4552 WebGLBuffer* buffer = 0;
4554 case GraphicsContext3D::ELEMENT_ARRAY_BUFFER:
4555 buffer = m_boundVertexArrayObject->getElementArrayBuffer().get();
4557 case GraphicsContext3D::ARRAY_BUFFER:
4558 buffer = m_boundArrayBuffer.get();
4561 m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
4565 m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
4569 case GraphicsContext3D::STREAM_DRAW:
4570 case GraphicsContext3D::STATIC_DRAW:
4571 case GraphicsContext3D::DYNAMIC_DRAW:
4574 m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
4578 bool WebGLRenderingContext::validateHTMLImageElement(HTMLImageElement* image)
4580 if (!image || !image->cachedImage()) {
4581 m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
4584 const KURL& url = image->cachedImage()->response().url();
4585 if (url.isNull() || url.isEmpty() || !url.isValid()) {
4586 m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
4592 void WebGLRenderingContext::vertexAttribfImpl(GC3Duint index, GC3Dsizei expectedSize, GC3Dfloat v0, GC3Dfloat v1, GC3Dfloat v2, GC3Dfloat v3)
4594 if (isContextLost())
4596 if (index >= m_maxVertexAttribs) {
4597 m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
4600 // In GL, we skip setting vertexAttrib0 values.
4601 if (index || isGLES2Compliant()) {
4602 switch (expectedSize) {
4604 m_context->vertexAttrib1f(index, v0);
4607 m_context->vertexAttrib2f(index, v0, v1);
4610 m_context->vertexAttrib3f(index, v0, v1, v2);
4613 m_context->vertexAttrib4f(index, v0, v1, v2, v3);
4616 cleanupAfterGraphicsCall(false);
4618 VertexAttribValue& attribValue = m_vertexAttribValue[index];
4619 attribValue.value[0] = v0;
4620 attribValue.value[1] = v1;
4621 attribValue.value[2] = v2;
4622 attribValue.value[3] = v3;
4625 void WebGLRenderingContext::vertexAttribfvImpl(GC3Duint index, Float32Array* v, GC3Dsizei expectedSize)
4627 if (isContextLost())
4630 m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
4633 vertexAttribfvImpl(index, v->data(), v->length(), expectedSize);
4636 void WebGLRenderingContext::vertexAttribfvImpl(GC3Duint index, GC3Dfloat* v, GC3Dsizei size, GC3Dsizei expectedSize)
4638 if (isContextLost())
4641 m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
4644 if (size < expectedSize) {
4645 m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
4648 if (index >= m_maxVertexAttribs) {
4649 m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
4652 // In GL, we skip setting vertexAttrib0 values.
4653 if (index || isGLES2Compliant()) {
4654 switch (expectedSize) {
4656 m_context->vertexAttrib1fv(index, v);
4659 m_context->vertexAttrib2fv(index, v);
4662 m_context->vertexAttrib3fv(index, v);
4665 m_context->vertexAttrib4fv(index, v);
4668 cleanupAfterGraphicsCall(false);
4670 VertexAttribValue& attribValue = m_vertexAttribValue[index];
4671 attribValue.initValue();
4672 for (int ii = 0; ii < expectedSize; ++ii)
4673 attribValue.value[ii] = v[ii];
4676 void WebGLRenderingContext::initVertexAttrib0()
4678 WebGLVertexArrayObjectOES::VertexAttribState& state = m_boundVertexArrayObject->getVertexAttribState(0);
4680 m_vertexAttrib0Buffer = createBuffer();
4681 m_context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, m_vertexAttrib0Buffer->object());
4682 m_context->bufferData(GraphicsContext3D::ARRAY_BUFFER, 0, GraphicsContext3D::DYNAMIC_DRAW);
4683 m_context->vertexAttribPointer(0, 4, GraphicsContext3D::FLOAT, false, 0, 0);
4684 state.bufferBinding = m_vertexAttrib0Buffer;
4685 m_context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, 0);
4686 m_context->enableVertexAttribArray(0);
4687 m_vertexAttrib0BufferSize = 0;
4688 m_vertexAttrib0BufferValue[0] = 0.0f;
4689 m_vertexAttrib0BufferValue[1] = 0.0f;
4690 m_vertexAttrib0BufferValue[2] = 0.0f;
4691 m_vertexAttrib0BufferValue[3] = 1.0f;
4692 m_forceAttrib0BufferRefill = false;
4693 m_vertexAttrib0UsedBefore = false;
4696 bool WebGLRenderingContext::simulateVertexAttrib0(GC3Dsizei numVertex)
4698 const WebGLVertexArrayObjectOES::VertexAttribState& state = m_boundVertexArrayObject->getVertexAttribState(0);
4699 const VertexAttribValue& attribValue = m_vertexAttribValue[0];
4700 if (!m_currentProgram)
4702 bool usingVertexAttrib0 = m_currentProgram->isUsingVertexAttrib0();
4703 if (usingVertexAttrib0)
4704 m_vertexAttrib0UsedBefore = true;
4705 if (state.enabled && usingVertexAttrib0)
4707 if (!usingVertexAttrib0 && !m_vertexAttrib0UsedBefore)
4709 m_vertexAttrib0UsedBefore = true;
4710 m_context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, m_vertexAttrib0Buffer->object());
4711 GC3Dsizeiptr bufferDataSize = (numVertex + 1) * 4 * sizeof(GC3Dfloat);
4712 if (bufferDataSize > m_vertexAttrib0BufferSize) {
4713 m_context->bufferData(GraphicsContext3D::ARRAY_BUFFER, bufferDataSize, 0, GraphicsContext3D::DYNAMIC_DRAW);
4714 m_vertexAttrib0BufferSize = bufferDataSize;
4715 m_forceAttrib0BufferRefill = true;
4717 if (usingVertexAttrib0
4718 && (m_forceAttrib0BufferRefill
4719 || attribValue.value[0] != m_vertexAttrib0BufferValue[0]
4720 || attribValue.value[1] != m_vertexAttrib0BufferValue[1]
4721 || attribValue.value[2] != m_vertexAttrib0BufferValue[2]
4722 || attribValue.value[3] != m_vertexAttrib0BufferValue[3])) {
4723 OwnArrayPtr<GC3Dfloat> bufferData = adoptArrayPtr(new GC3Dfloat[(numVertex + 1) * 4]);
4724 for (GC3Dsizei ii = 0; ii < numVertex + 1; ++ii) {
4725 bufferData[ii * 4] = attribValue.value[0];
4726 bufferData[ii * 4 + 1] = attribValue.value[1];
4727 bufferData[ii * 4 + 2] = attribValue.value[2];
4728 bufferData[ii * 4 + 3] = attribValue.value[3];
4730 m_vertexAttrib0BufferValue[0] = attribValue.value[0];
4731 m_vertexAttrib0BufferValue[1] = attribValue.value[1];
4732 m_vertexAttrib0BufferValue[2] = attribValue.value[2];
4733 m_vertexAttrib0BufferValue[3] = attribValue.value[3];
4734 m_forceAttrib0BufferRefill = false;
4735 m_context->bufferSubData(GraphicsContext3D::ARRAY_BUFFER, 0, bufferDataSize, bufferData.get());
4737 m_context->vertexAttribPointer(0, 4, GraphicsContext3D::FLOAT, 0, 0, 0);
4741 void WebGLRenderingContext::restoreStatesAfterVertexAttrib0Simulation()
4743 const WebGLVertexArrayObjectOES::VertexAttribState& state = m_boundVertexArrayObject->getVertexAttribState(0);
4744 if (state.bufferBinding != m_vertexAttrib0Buffer) {
4745 m_context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, objectOrZero(state.bufferBinding.get()));
4746 m_context->vertexAttribPointer(0, state.size, state.type, state.normalized, state.originalStride, state.offset);
4748 m_context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, objectOrZero(m_boundArrayBuffer.get()));
4751 void WebGLRenderingContext::loseContext()
4753 m_contextLost = true;
4755 detachAndRemoveAllObjects();
4757 // There is no direct way to clear errors from a GL implementation and
4758 // looping until getError() becomes NO_ERROR might cause an infinite loop if
4759 // the driver or context implementation had a bug. So, loop a reasonably
4760 // large number of times to clear any existing errors.
4761 for (int i = 0; i < 100; ++i) {
4762 if (m_context->getError() == GraphicsContext3D::NO_ERROR)
4765 m_context->synthesizeGLError(GraphicsContext3D::CONTEXT_LOST_WEBGL);
4767 RefPtr<WebGLContextEvent> event = WebGLContextEvent::create(eventNames().webglcontextlostEvent, false, true, "");
4768 canvas()->dispatchEvent(event);
4769 m_restoreAllowed = event->defaultPrevented();
4772 void WebGLRenderingContext::maybeRestoreContext(WebGLRenderingContext::LostContextMode mode)
4774 if (!m_contextLost) {
4775 ASSERT(mode == SyntheticLostContext);
4776 m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
4780 // The rendering context is not restored unless the default
4781 // behavior of the webglcontextlost event was prevented earlier.
4782 if (!m_restoreAllowed) {
4783 if (mode == SyntheticLostContext)
4784 m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
4788 int contextLostReason = m_context->getExtensions()->getGraphicsResetStatusARB();
4790 switch (contextLostReason) {
4791 case GraphicsContext3D::NO_ERROR:
4792 // The GraphicsContext3D implementation might not fully
4793 // support GL_ARB_robustness semantics yet. Alternatively, the
4794 // WebGL WEBKIT_lose_context extension might have been used to
4795 // force a lost context.
4797 case Extensions3D::GUILTY_CONTEXT_RESET_ARB:
4798 // The rendering context is not restored if this context was
4799 // guilty of causing the graphics reset.
4800 printWarningToConsole("WARNING: WebGL content on the page caused the graphics card to reset; not restoring the context");
4802 case Extensions3D::INNOCENT_CONTEXT_RESET_ARB:
4803 // Always allow the context to be restored.
4805 case Extensions3D::UNKNOWN_CONTEXT_RESET_ARB:
4806 // Warn. Ideally, prompt the user telling them that WebGL
4807 // content on the page might have caused the graphics card to
4808 // reset and ask them whether they want to continue running
4809 // the content. Only if they say "yes" should we start
4810 // attempting to restore the context.
4811 printWarningToConsole("WARNING: WebGL content on the page might have caused the graphics card to reset");
4815 RefPtr<GraphicsContext3D> context(GraphicsContext3D::create(m_attributes, canvas()->document()->view()->root()->hostWindow()));
4817 if (mode == RealLostContext)
4818 m_restoreTimer.startOneShot(secondsBetweenRestoreAttempts);
4820 // This likely shouldn't happen but is the best way to report it to the WebGL app.
4821 m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
4825 m_context = context;
4826 m_contextLost = false;
4827 initializeNewContext();
4828 canvas()->dispatchEvent(WebGLContextEvent::create(eventNames().webglcontextrestoredEvent, false, true, ""));
4831 WebGLRenderingContext::LRUImageBufferCache::LRUImageBufferCache(int capacity)
4832 : m_buffers(adoptArrayPtr(new OwnPtr<ImageBuffer>[capacity]))
4833 , m_capacity(capacity)
4837 ImageBuffer* WebGLRenderingContext::LRUImageBufferCache::imageBuffer(const IntSize& size)
4840 for (i = 0; i < m_capacity; ++i) {
4841 ImageBuffer* buf = m_buffers[i].get();
4844 if (buf->size() != size)
4850 OwnPtr<ImageBuffer> temp = ImageBuffer::create(size);
4853 i = std::min(m_capacity - 1, i);
4854 m_buffers[i] = temp.release();
4856 ImageBuffer* buf = m_buffers[i].get();
4861 void WebGLRenderingContext::LRUImageBufferCache::bubbleToFront(int idx)
4863 for (int i = idx; i > 0; --i)
4864 m_buffers[i].swap(m_buffers[i-1]);
4867 } // namespace WebCore
4869 #endif // ENABLE(WEBGL)