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 "CheckedInt.h"
35 #include "DOMWindow.h"
36 #include "EXTTextureFilterAnisotropic.h"
37 #include "ExceptionCode.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"
54 #include "WebGLActiveInfo.h"
55 #include "WebGLBuffer.h"
56 #include "WebGLCompressedTextureS3TC.h"
57 #include "WebGLContextAttributes.h"
58 #include "WebGLContextEvent.h"
59 #include "WebGLContextGroup.h"
60 #include "WebGLDebugRendererInfo.h"
61 #include "WebGLDebugShaders.h"
62 #include "WebGLDepthTexture.h"
63 #include "WebGLFramebuffer.h"
64 #include "WebGLLoseContext.h"
65 #include "WebGLProgram.h"
66 #include "WebGLRenderbuffer.h"
67 #include "WebGLShader.h"
68 #include "WebGLShaderPrecisionFormat.h"
69 #include "WebGLTexture.h"
70 #include "WebGLUniformLocation.h"
72 #include <wtf/OwnArrayPtr.h>
73 #include <wtf/PassOwnArrayPtr.h>
74 #include <wtf/Uint16Array.h>
75 #include <wtf/Uint32Array.h>
76 #include <wtf/text/StringBuilder.h>
84 const double secondsBetweenRestoreAttempts = 1.0;
85 const int maxGLErrorsAllowedToConsole = 256;
89 class ScopedDrawingBufferBinder {
91 ScopedDrawingBufferBinder(DrawingBuffer* drawingBuffer, WebGLFramebuffer* framebufferBinding)
92 : m_drawingBuffer(drawingBuffer)
93 , m_framebufferBinding(framebufferBinding)
95 // Commit DrawingBuffer if needed (e.g., for multisampling)
96 if (!m_framebufferBinding && m_drawingBuffer)
97 m_drawingBuffer->commit();
100 ~ScopedDrawingBufferBinder()
102 // Restore DrawingBuffer if needed
103 if (!m_framebufferBinding && m_drawingBuffer)
104 m_drawingBuffer->bind();
108 DrawingBuffer* m_drawingBuffer;
109 WebGLFramebuffer* m_framebufferBinding;
112 Platform3DObject objectOrZero(WebGLObject* object)
114 return object ? object->object() : 0;
117 void clip1D(GC3Dint start, GC3Dsizei range, GC3Dsizei sourceRange, GC3Dint* clippedStart, GC3Dsizei* clippedRange)
119 ASSERT(clippedStart && clippedRange);
124 GC3Dint end = start + range;
125 if (end > sourceRange)
126 range -= end - sourceRange;
127 *clippedStart = start;
128 *clippedRange = range;
131 // Returns false if no clipping is necessary, i.e., x, y, width, height stay the same.
132 bool clip2D(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height,
133 GC3Dsizei sourceWidth, GC3Dsizei sourceHeight,
134 GC3Dint* clippedX, GC3Dint* clippedY, GC3Dsizei* clippedWidth, GC3Dsizei*clippedHeight)
136 ASSERT(clippedX && clippedY && clippedWidth && clippedHeight);
137 clip1D(x, width, sourceWidth, clippedX, clippedWidth);
138 clip1D(y, height, sourceHeight, clippedY, clippedHeight);
139 return (*clippedX != x || *clippedY != y || *clippedWidth != width || *clippedHeight != height);
142 GC3Dint clamp(GC3Dint value, GC3Dint min, GC3Dint max)
151 // Return true if a character belongs to the ASCII subset as defined in
152 // GLSL ES 1.0 spec section 3.1.
153 bool validateCharacter(unsigned char c)
155 // Printing characters are valid except " $ ` @ \ ' DEL.
156 if (c >= 32 && c <= 126
157 && c != '"' && c != '$' && c != '`' && c != '@' && c != '\\' && c != '\'')
159 // Horizontal tab, line feed, vertical tab, form feed, carriage return
161 if (c >= 9 && c <= 13)
166 bool isPrefixReserved(const String& name)
168 if (name.startsWith("gl_") || name.startsWith("webgl_") || name.startsWith("_webgl_"))
173 // Strips comments from shader text. This allows non-ASCII characters
174 // to be used in comments without potentially breaking OpenGL
175 // implementations not expecting characters outside the GLSL ES set.
176 class StripComments {
178 StripComments(const String& str)
179 : m_parseState(BeginningOfLine)
180 , m_sourceString(str)
181 , m_length(str.length())
189 return m_builder.toString();
193 bool hasMoreCharacters()
195 return (m_position < m_length);
200 while (hasMoreCharacters()) {
202 // process() might advance the position.
203 if (hasMoreCharacters())
210 bool peek(UChar& character)
212 if (m_position + 1 >= m_length)
214 character = m_sourceString[m_position + 1];
220 ASSERT(m_position < m_length);
221 return m_sourceString[m_position];
229 bool isNewline(UChar character)
231 // Don't attempt to canonicalize newline related characters.
232 return (character == '\n' || character == '\r');
235 void emit(UChar character)
237 m_builder.append(character);
241 // Have not seen an ASCII non-whitespace character yet on
242 // this line. Possible that we might see a preprocessor
246 // Have seen at least one ASCII non-whitespace character
250 // Handling a preprocessor directive. Passes through all
251 // characters up to the end of the line. Disables comment
253 InPreprocessorDirective,
255 // Handling a single-line comment. The comment text is
256 // replaced with a single space.
259 // Handling a multi-line comment. Newlines are passed
260 // through to preserve line numbers.
264 ParseState m_parseState;
265 String m_sourceString;
268 StringBuilder m_builder;
271 void StripComments::process(UChar c)
274 // No matter what state we are in, pass through newlines
275 // so we preserve line numbers.
278 if (m_parseState != InMultiLineComment)
279 m_parseState = BeginningOfLine;
285 switch (m_parseState) {
286 case BeginningOfLine:
287 if (WTF::isASCIISpace(c)) {
293 m_parseState = InPreprocessorDirective;
298 // Transition to normal state and re-handle character.
299 m_parseState = MiddleOfLine;
304 if (c == '/' && peek(temp)) {
306 m_parseState = InSingleLineComment;
313 m_parseState = InMultiLineComment;
314 // Emit the comment start in case the user has
315 // an unclosed comment and we want to later
327 case InPreprocessorDirective:
328 // No matter what the character is, just pass it
329 // through. Do not parse comments in this state. This
330 // might not be the right thing to do long term, but it
331 // should handle the #error preprocessor directive.
335 case InSingleLineComment:
336 // The newline code at the top of this function takes care
337 // of resetting our state when we get out of the
338 // single-line comment. Swallow all other characters.
341 case InMultiLineComment:
342 if (c == '*' && peek(temp) && temp == '/') {
345 m_parseState = MiddleOfLine;
350 // Swallow all other characters. Unclear whether we may
351 // want or need to just emit a space per character to try
352 // to preserve column numbers for debugging purposes.
356 } // namespace anonymous
358 class WebGLStateRestorer {
360 WebGLStateRestorer(WebGLRenderingContext* context,
367 ~WebGLStateRestorer()
369 m_context->cleanupAfterGraphicsCall(m_changed);
373 WebGLRenderingContext* m_context;
377 class WebGLRenderingContextLostCallback : public GraphicsContext3D::ContextLostCallback {
379 explicit WebGLRenderingContextLostCallback(WebGLRenderingContext* cb) : m_context(cb) { }
380 virtual void onContextLost() { m_context->forceLostContext(WebGLRenderingContext::RealLostContext); }
381 virtual ~WebGLRenderingContextLostCallback() {}
383 WebGLRenderingContext* m_context;
386 class WebGLRenderingContextErrorMessageCallback : public GraphicsContext3D::ErrorMessageCallback {
388 explicit WebGLRenderingContextErrorMessageCallback(WebGLRenderingContext* cb) : m_context(cb) { }
389 virtual void onErrorMessage(const String& message, GC3Dint) { m_context->printGLErrorToConsole(message); }
390 virtual ~WebGLRenderingContextErrorMessageCallback() { }
392 WebGLRenderingContext* m_context;
395 PassOwnPtr<WebGLRenderingContext> WebGLRenderingContext::create(HTMLCanvasElement* canvas, WebGLContextAttributes* attrs)
397 HostWindow* hostWindow = canvas->document()->view()->root()->hostWindow();
398 GraphicsContext3D::Attributes attributes = attrs ? attrs->attributes() : GraphicsContext3D::Attributes();
400 if (attributes.antialias) {
401 Page* p = canvas->document()->page();
402 if (p && !p->settings()->openGLMultisamplingEnabled())
403 attributes.antialias = false;
406 attributes.noExtensions = true;
407 #if PLATFORM(CHROMIUM)
408 attributes.shareResources = true;
410 attributes.shareResources = false;
412 attributes.preferDiscreteGPU = true;
415 RefPtr<GraphicsContext3D> context(GraphicsContext3D::create(attributes, hostWindow));
417 if (!context || !context->makeContextCurrent()) {
418 canvas->dispatchEvent(WebGLContextEvent::create(eventNames().webglcontextcreationerrorEvent, false, true, "Could not create a WebGL context."));
422 return adoptPtr(new WebGLRenderingContext(canvas, context, attributes));
425 WebGLRenderingContext::WebGLRenderingContext(HTMLCanvasElement* passedCanvas, PassRefPtr<GraphicsContext3D> context,
426 GraphicsContext3D::Attributes attributes)
427 : CanvasRenderingContext(passedCanvas)
430 , m_dispatchContextLostEventTimer(this, &WebGLRenderingContext::dispatchContextLostEvent)
431 , m_restoreAllowed(false)
432 , m_restoreTimer(this, &WebGLRenderingContext::maybeRestoreContext)
434 , m_contextLost(false)
435 , m_contextLostMode(SyntheticLostContext)
436 , m_attributes(attributes)
437 , m_synthesizedErrorsToConsole(false)
438 , m_numGLErrorsToConsoleAllowed(maxGLErrorsAllowedToConsole)
441 m_contextGroup = WebGLContextGroup::create();
442 m_contextGroup->addContext(this);
444 m_maxViewportDims[0] = m_maxViewportDims[1] = 0;
445 m_context->getIntegerv(GraphicsContext3D::MAX_VIEWPORT_DIMS, m_maxViewportDims);
447 #if PLATFORM(CHROMIUM)
448 // Create the DrawingBuffer and initialize the platform layer.
449 DrawingBuffer::PreserveDrawingBuffer preserve = m_attributes.preserveDrawingBuffer ? DrawingBuffer::Preserve : DrawingBuffer::Discard;
450 DrawingBuffer::AlphaRequirement alpha = m_attributes.alpha ? DrawingBuffer::Alpha : DrawingBuffer::Opaque;
451 m_drawingBuffer = DrawingBuffer::create(m_context.get(), clampedCanvasSize(), preserve, alpha);
455 m_drawingBuffer->bind();
458 initializeNewContext();
461 void WebGLRenderingContext::initializeNewContext()
463 ASSERT(!m_contextLost);
464 m_needsUpdate = true;
465 m_markedCanvasDirty = false;
466 m_activeTextureUnit = 0;
468 m_unpackAlignment = 4;
469 m_unpackFlipY = false;
470 m_unpackPremultiplyAlpha = false;
471 m_unpackColorspaceConversion = GraphicsContext3D::BROWSER_DEFAULT_WEBGL;
472 m_boundArrayBuffer = 0;
473 m_currentProgram = 0;
474 m_framebufferBinding = 0;
475 m_renderbufferBinding = 0;
477 m_stencilEnabled = false;
478 m_stencilMask = 0xFFFFFFFF;
479 m_stencilMaskBack = 0xFFFFFFFF;
480 m_stencilFuncRef = 0;
481 m_stencilFuncRefBack = 0;
482 m_stencilFuncMask = 0xFFFFFFFF;
483 m_stencilFuncMaskBack = 0xFFFFFFFF;
484 m_layerCleared = false;
485 m_numGLErrorsToConsoleAllowed = maxGLErrorsAllowedToConsole;
487 m_clearColor[0] = m_clearColor[1] = m_clearColor[2] = m_clearColor[3] = 0;
488 m_scissorEnabled = false;
491 m_colorMask[0] = m_colorMask[1] = m_colorMask[2] = m_colorMask[3] = true;
493 GC3Dint numCombinedTextureImageUnits = 0;
494 m_context->getIntegerv(GraphicsContext3D::MAX_COMBINED_TEXTURE_IMAGE_UNITS, &numCombinedTextureImageUnits);
495 m_textureUnits.clear();
496 m_textureUnits.resize(numCombinedTextureImageUnits);
498 GC3Dint numVertexAttribs = 0;
499 m_context->getIntegerv(GraphicsContext3D::MAX_VERTEX_ATTRIBS, &numVertexAttribs);
500 m_maxVertexAttribs = numVertexAttribs;
502 m_maxTextureSize = 0;
503 m_context->getIntegerv(GraphicsContext3D::MAX_TEXTURE_SIZE, &m_maxTextureSize);
504 m_maxTextureLevel = WebGLTexture::computeLevelCount(m_maxTextureSize, m_maxTextureSize);
505 m_maxCubeMapTextureSize = 0;
506 m_context->getIntegerv(GraphicsContext3D::MAX_CUBE_MAP_TEXTURE_SIZE, &m_maxCubeMapTextureSize);
507 m_maxCubeMapTextureLevel = WebGLTexture::computeLevelCount(m_maxCubeMapTextureSize, m_maxCubeMapTextureSize);
508 m_maxRenderbufferSize = 0;
509 m_context->getIntegerv(GraphicsContext3D::MAX_RENDERBUFFER_SIZE, &m_maxRenderbufferSize);
511 m_defaultVertexArrayObject = WebGLVertexArrayObjectOES::create(this, WebGLVertexArrayObjectOES::VaoTypeDefault);
512 addContextObject(m_defaultVertexArrayObject.get());
513 m_boundVertexArrayObject = m_defaultVertexArrayObject;
515 m_vertexAttribValue.resize(m_maxVertexAttribs);
517 if (!isGLES2NPOTStrict())
518 createFallbackBlackTextures1x1();
519 if (!isGLES2Compliant())
522 IntSize canvasSize = clampedCanvasSize();
524 m_drawingBuffer->reset(canvasSize);
526 m_context->reshape(canvasSize.width(), canvasSize.height());
527 m_context->viewport(0, 0, canvasSize.width(), canvasSize.height());
528 m_context->scissor(0, 0, canvasSize.width(), canvasSize.height());
530 m_context->setContextLostCallback(adoptPtr(new WebGLRenderingContextLostCallback(this)));
531 m_context->setErrorMessageCallback(adoptPtr(new WebGLRenderingContextErrorMessageCallback(this)));
534 void WebGLRenderingContext::setupFlags()
538 Page* p = canvas()->document()->page();
539 if (p && p->settings()->webGLErrorsToConsoleEnabled())
540 m_synthesizedErrorsToConsole = true;
542 m_isGLES2Compliant = m_context->isGLES2Compliant();
543 m_isErrorGeneratedOnOutOfBoundsAccesses = m_context->getExtensions()->isEnabled("GL_CHROMIUM_strict_attribs");
544 m_isResourceSafe = m_context->getExtensions()->isEnabled("GL_CHROMIUM_resource_safe");
545 if (m_isGLES2Compliant) {
546 m_isGLES2NPOTStrict = !m_context->getExtensions()->isEnabled("GL_OES_texture_npot");
547 m_isDepthStencilSupported = m_context->getExtensions()->isEnabled("GL_OES_packed_depth_stencil");
549 m_isGLES2NPOTStrict = !m_context->getExtensions()->isEnabled("GL_ARB_texture_non_power_of_two");
550 m_isDepthStencilSupported = m_context->getExtensions()->isEnabled("GL_EXT_packed_depth_stencil");
554 bool WebGLRenderingContext::allowPrivilegedExtensions() const
556 Page* p = canvas()->document()->page();
557 if (p && p->settings())
558 return p->settings()->privilegedWebGLExtensionsEnabled();
562 void WebGLRenderingContext::addCompressedTextureFormat(GC3Denum format)
564 if (!m_compressedTextureFormats.contains(format))
565 m_compressedTextureFormats.append(format);
568 WebGLRenderingContext::~WebGLRenderingContext()
570 // Remove all references to WebGLObjects so if they are the last reference
571 // they will be freed before the last context is removed from the context group.
572 m_boundArrayBuffer = 0;
573 m_defaultVertexArrayObject = 0;
574 m_boundVertexArrayObject = 0;
575 m_vertexAttrib0Buffer = 0;
576 m_currentProgram = 0;
577 m_framebufferBinding = 0;
578 m_renderbufferBinding = 0;
580 for (size_t i = 0; i < m_textureUnits.size(); ++i) {
581 m_textureUnits[i].m_texture2DBinding = 0;
582 m_textureUnits[i].m_textureCubeMapBinding = 0;
585 m_blackTexture2D = 0;
586 m_blackTextureCubeMap = 0;
588 detachAndRemoveAllObjects();
589 m_context->setContextLostCallback(nullptr);
590 m_context->setErrorMessageCallback(nullptr);
591 m_contextGroup->removeContext(this);
594 void WebGLRenderingContext::markContextChanged()
596 if (m_framebufferBinding)
599 m_context->markContextChanged();
601 m_layerCleared = false;
602 #if USE(ACCELERATED_COMPOSITING)
603 RenderBox* renderBox = canvas()->renderBox();
604 if (renderBox && renderBox->hasAcceleratedCompositing()) {
605 m_markedCanvasDirty = true;
606 renderBox->contentChanged(CanvasChanged);
609 if (!m_markedCanvasDirty) {
610 m_markedCanvasDirty = true;
611 canvas()->didDraw(FloatRect(FloatPoint(0, 0), clampedCanvasSize()));
613 #if USE(ACCELERATED_COMPOSITING)
618 bool WebGLRenderingContext::clearIfComposited(GC3Dbitfield mask)
623 if (!m_context->layerComposited() || m_layerCleared
624 || m_attributes.preserveDrawingBuffer || (mask && m_framebufferBinding))
627 RefPtr<WebGLContextAttributes> contextAttributes = getContextAttributes();
629 // Determine if it's possible to combine the clear the user asked for and this clear.
630 bool combinedClear = mask && !m_scissorEnabled;
632 m_context->disable(GraphicsContext3D::SCISSOR_TEST);
633 if (combinedClear && (mask & GraphicsContext3D::COLOR_BUFFER_BIT))
634 m_context->clearColor(m_colorMask[0] ? m_clearColor[0] : 0,
635 m_colorMask[1] ? m_clearColor[1] : 0,
636 m_colorMask[2] ? m_clearColor[2] : 0,
637 m_colorMask[3] ? m_clearColor[3] : 0);
639 m_context->clearColor(0, 0, 0, 0);
640 m_context->colorMask(true, true, true, true);
641 GC3Dbitfield clearMask = GraphicsContext3D::COLOR_BUFFER_BIT;
642 if (contextAttributes->depth()) {
643 if (!combinedClear || !m_depthMask || !(mask & GraphicsContext3D::DEPTH_BUFFER_BIT))
644 m_context->clearDepth(1.0f);
645 clearMask |= GraphicsContext3D::DEPTH_BUFFER_BIT;
646 m_context->depthMask(true);
648 if (contextAttributes->stencil()) {
649 if (combinedClear && (mask & GraphicsContext3D::STENCIL_BUFFER_BIT))
650 m_context->clearStencil(m_clearStencil & m_stencilMask);
652 m_context->clearStencil(0);
653 clearMask |= GraphicsContext3D::STENCIL_BUFFER_BIT;
654 m_context->stencilMaskSeparate(GraphicsContext3D::FRONT, 0xFFFFFFFF);
657 m_drawingBuffer->clearFramebuffers(clearMask);
659 if (m_framebufferBinding)
660 m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, 0);
661 m_context->clear(clearMask);
664 restoreStateAfterClear();
665 if (m_framebufferBinding)
666 m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, objectOrZero(m_framebufferBinding.get()));
667 m_layerCleared = true;
669 return combinedClear;
672 void WebGLRenderingContext::restoreStateAfterClear()
674 // Restore the state that the context set.
675 if (m_scissorEnabled)
676 m_context->enable(GraphicsContext3D::SCISSOR_TEST);
677 m_context->clearColor(m_clearColor[0], m_clearColor[1],
678 m_clearColor[2], m_clearColor[3]);
679 m_context->colorMask(m_colorMask[0], m_colorMask[1],
680 m_colorMask[2], m_colorMask[3]);
681 m_context->clearDepth(m_clearDepth);
682 m_context->clearStencil(m_clearStencil);
683 m_context->stencilMaskSeparate(GraphicsContext3D::FRONT, m_stencilMask);
684 m_context->depthMask(m_depthMask);
687 void WebGLRenderingContext::markLayerComposited()
689 m_context->markLayerComposited();
692 void WebGLRenderingContext::paintRenderingResultsToCanvas()
694 // Until the canvas is written to by the application, the clear that
695 // happened after it was composited should be ignored by the compositor.
696 if (m_context->layerComposited() && !m_attributes.preserveDrawingBuffer) {
697 m_context->paintCompositedResultsToCanvas(canvas()->buffer());
699 #if USE(ACCELERATED_COMPOSITING) && PLATFORM(CHROMIUM)
701 m_drawingBuffer->paintCompositedResultsToCanvas(canvas()->buffer());
704 canvas()->makePresentationCopy();
706 canvas()->clearPresentationCopy();
709 if (!m_markedCanvasDirty && !m_layerCleared)
712 canvas()->clearCopiedImage();
713 m_markedCanvasDirty = false;
716 m_drawingBuffer->commit();
717 m_context->paintRenderingResultsToCanvas(canvas()->buffer(), m_drawingBuffer.get());
719 if (m_drawingBuffer) {
720 if (m_framebufferBinding)
721 m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, objectOrZero(m_framebufferBinding.get()));
723 m_drawingBuffer->bind();
727 PassRefPtr<ImageData> WebGLRenderingContext::paintRenderingResultsToImageData()
731 m_drawingBuffer->commit();
732 RefPtr<ImageData> imageData = m_context->paintRenderingResultsToImageData(m_drawingBuffer.get());
734 if (m_drawingBuffer) {
735 if (m_framebufferBinding)
736 m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, objectOrZero(m_framebufferBinding.get()));
738 m_drawingBuffer->bind();
744 void WebGLRenderingContext::reshape(int width, int height)
746 // This is an approximation because at WebGLRenderingContext level we don't
747 // know if the underlying FBO uses textures or renderbuffers.
748 GC3Dint maxSize = std::min(m_maxTextureSize, m_maxRenderbufferSize);
749 // Limit drawing buffer size to 4k to avoid memory exhaustion.
750 const int sizeUpperLimit = 4096;
751 maxSize = std::min(maxSize, sizeUpperLimit);
752 GC3Dint maxWidth = std::min(maxSize, m_maxViewportDims[0]);
753 GC3Dint maxHeight = std::min(maxSize, m_maxViewportDims[1]);
754 width = clamp(width, 1, maxWidth);
755 height = clamp(height, 1, maxHeight);
758 #if USE(ACCELERATED_COMPOSITING)
759 RenderBox* renderBox = canvas()->renderBox();
760 if (renderBox && renderBox->hasAcceleratedCompositing())
761 renderBox->contentChanged(CanvasChanged);
763 m_needsUpdate = false;
766 // We don't have to mark the canvas as dirty, since the newly created image buffer will also start off
767 // clear (and this matches what reshape will do).
768 if (m_drawingBuffer) {
769 m_drawingBuffer->reset(IntSize(width, height));
770 restoreStateAfterClear();
772 m_context->reshape(width, height);
774 m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, objectOrZero(m_textureUnits[m_activeTextureUnit].m_texture2DBinding.get()));
775 m_context->bindRenderbuffer(GraphicsContext3D::RENDERBUFFER, objectOrZero(m_renderbufferBinding.get()));
776 if (m_framebufferBinding)
777 m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, objectOrZero(m_framebufferBinding.get()));
780 int WebGLRenderingContext::drawingBufferWidth() const
783 return m_drawingBuffer->size().width();
785 return m_context->getInternalFramebufferSize().width();
788 int WebGLRenderingContext::drawingBufferHeight() const
791 return m_drawingBuffer->size().height();
793 return m_context->getInternalFramebufferSize().height();
796 unsigned int WebGLRenderingContext::sizeInBytes(GC3Denum type)
799 case GraphicsContext3D::BYTE:
800 return sizeof(GC3Dbyte);
801 case GraphicsContext3D::UNSIGNED_BYTE:
802 return sizeof(GC3Dubyte);
803 case GraphicsContext3D::SHORT:
804 return sizeof(GC3Dshort);
805 case GraphicsContext3D::UNSIGNED_SHORT:
806 return sizeof(GC3Dushort);
807 case GraphicsContext3D::INT:
808 return sizeof(GC3Dint);
809 case GraphicsContext3D::UNSIGNED_INT:
810 return sizeof(GC3Duint);
811 case GraphicsContext3D::FLOAT:
812 return sizeof(GC3Dfloat);
814 ASSERT_NOT_REACHED();
818 void WebGLRenderingContext::activeTexture(GC3Denum texture, ExceptionCode& ec)
823 if (texture - GraphicsContext3D::TEXTURE0 >= m_textureUnits.size()) {
824 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "activeTexture", "texture unit out of range");
827 m_activeTextureUnit = texture - GraphicsContext3D::TEXTURE0;
828 m_context->activeTexture(texture);
831 m_drawingBuffer->setActiveTextureUnit(texture);
833 cleanupAfterGraphicsCall(false);
836 void WebGLRenderingContext::attachShader(WebGLProgram* program, WebGLShader* shader, ExceptionCode& ec)
839 if (isContextLost() || !validateWebGLObject("attachShader", program) || !validateWebGLObject("attachShader", shader))
841 if (!program->attachShader(shader)) {
842 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "attachShader", "shader attachment already has shader");
845 m_context->attachShader(objectOrZero(program), objectOrZero(shader));
846 shader->onAttached();
847 cleanupAfterGraphicsCall(false);
850 void WebGLRenderingContext::bindAttribLocation(WebGLProgram* program, GC3Duint index, const String& name, ExceptionCode& ec)
853 if (isContextLost() || !validateWebGLObject("bindAttribLocation", program))
855 if (!validateLocationLength("bindAttribLocation", name))
857 if (!validateString("bindAttribLocation", name))
859 if (isPrefixReserved(name)) {
860 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "bindAttribLocation", "reserved prefix");
863 if (index >= m_maxVertexAttribs) {
864 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "bindAttribLocation", "index out of range");
867 m_context->bindAttribLocation(objectOrZero(program), index, name);
868 cleanupAfterGraphicsCall(false);
871 bool WebGLRenderingContext::checkObjectToBeBound(const char* functionName, WebGLObject* object, bool& deleted)
877 if (!object->validate(contextGroup(), this)) {
878 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "object not from this context");
881 deleted = !object->object();
886 void WebGLRenderingContext::bindBuffer(GC3Denum target, WebGLBuffer* buffer, ExceptionCode& ec)
890 if (!checkObjectToBeBound("bindBuffer", buffer, deleted))
894 if (buffer && buffer->getTarget() && buffer->getTarget() != target) {
895 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "bindBuffer", "buffers can not be used with multiple targets");
898 if (target == GraphicsContext3D::ARRAY_BUFFER)
899 m_boundArrayBuffer = buffer;
900 else if (target == GraphicsContext3D::ELEMENT_ARRAY_BUFFER)
901 m_boundVertexArrayObject->setElementArrayBuffer(buffer);
903 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "bindBuffer", "invalid target");
907 m_context->bindBuffer(target, objectOrZero(buffer));
909 buffer->setTarget(target);
910 cleanupAfterGraphicsCall(false);
913 void WebGLRenderingContext::bindFramebuffer(GC3Denum target, WebGLFramebuffer* buffer, ExceptionCode& ec)
917 if (!checkObjectToBeBound("bindFramebuffer", buffer, deleted))
921 if (target != GraphicsContext3D::FRAMEBUFFER) {
922 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "bindFramebuffer", "invalid target");
925 m_framebufferBinding = buffer;
927 m_drawingBuffer->setFramebufferBinding(objectOrZero(m_framebufferBinding.get()));
928 if (!m_framebufferBinding && m_drawingBuffer) {
929 // Instead of binding fb 0, bind the drawing buffer.
930 m_drawingBuffer->bind();
932 m_context->bindFramebuffer(target, objectOrZero(buffer));
934 buffer->setHasEverBeenBound();
936 cleanupAfterGraphicsCall(false);
939 void WebGLRenderingContext::bindRenderbuffer(GC3Denum target, WebGLRenderbuffer* renderBuffer, ExceptionCode& ec)
943 if (!checkObjectToBeBound("bindRenderbuffer", renderBuffer, deleted))
947 if (target != GraphicsContext3D::RENDERBUFFER) {
948 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "bindRenderbuffer", "invalid target");
951 m_renderbufferBinding = renderBuffer;
952 m_context->bindRenderbuffer(target, objectOrZero(renderBuffer));
954 renderBuffer->setHasEverBeenBound();
955 cleanupAfterGraphicsCall(false);
958 void WebGLRenderingContext::bindTexture(GC3Denum target, WebGLTexture* texture, ExceptionCode& ec)
962 if (!checkObjectToBeBound("bindTexture", texture, deleted))
966 if (texture && texture->getTarget() && texture->getTarget() != target) {
967 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "bindTexture", "textures can not be used with multiple targets");
970 GC3Dint maxLevel = 0;
971 if (target == GraphicsContext3D::TEXTURE_2D) {
972 m_textureUnits[m_activeTextureUnit].m_texture2DBinding = texture;
973 maxLevel = m_maxTextureLevel;
975 if (m_drawingBuffer && !m_activeTextureUnit)
976 m_drawingBuffer->setTexture2DBinding(objectOrZero(texture));
978 } else if (target == GraphicsContext3D::TEXTURE_CUBE_MAP) {
979 m_textureUnits[m_activeTextureUnit].m_textureCubeMapBinding = texture;
980 maxLevel = m_maxCubeMapTextureLevel;
982 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "bindTexture", "invalid target");
985 m_context->bindTexture(target, objectOrZero(texture));
987 texture->setTarget(target, maxLevel);
989 // Note: previously we used to automatically set the TEXTURE_WRAP_R
990 // repeat mode to CLAMP_TO_EDGE for cube map textures, because OpenGL
991 // ES 2.0 doesn't expose this flag (a bug in the specification) and
992 // otherwise the application has no control over the seams in this
993 // dimension. However, it appears that supporting this properly on all
994 // platforms is fairly involved (will require a HashMap from texture ID
995 // in all ports), and we have not had any complaints, so the logic has
998 cleanupAfterGraphicsCall(false);
1001 void WebGLRenderingContext::blendColor(GC3Dfloat red, GC3Dfloat green, GC3Dfloat blue, GC3Dfloat alpha)
1003 if (isContextLost())
1005 m_context->blendColor(red, green, blue, alpha);
1006 cleanupAfterGraphicsCall(false);
1009 void WebGLRenderingContext::blendEquation(GC3Denum mode)
1011 if (isContextLost() || !validateBlendEquation("blendEquation", mode))
1013 m_context->blendEquation(mode);
1014 cleanupAfterGraphicsCall(false);
1017 void WebGLRenderingContext::blendEquationSeparate(GC3Denum modeRGB, GC3Denum modeAlpha)
1019 if (isContextLost() || !validateBlendEquation("blendEquation", modeRGB) || !validateBlendEquation("blendEquation", modeAlpha))
1021 m_context->blendEquationSeparate(modeRGB, modeAlpha);
1022 cleanupAfterGraphicsCall(false);
1026 void WebGLRenderingContext::blendFunc(GC3Denum sfactor, GC3Denum dfactor)
1028 if (isContextLost() || !validateBlendFuncFactors("blendFunc", sfactor, dfactor))
1030 m_context->blendFunc(sfactor, dfactor);
1031 cleanupAfterGraphicsCall(false);
1034 void WebGLRenderingContext::blendFuncSeparate(GC3Denum srcRGB, GC3Denum dstRGB, GC3Denum srcAlpha, GC3Denum dstAlpha)
1036 // Note: Alpha does not have the same restrictions as RGB.
1037 if (isContextLost() || !validateBlendFuncFactors("blendFunc", srcRGB, dstRGB))
1039 m_context->blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha);
1040 cleanupAfterGraphicsCall(false);
1043 void WebGLRenderingContext::bufferData(GC3Denum target, long long size, GC3Denum usage, ExceptionCode& ec)
1046 if (isContextLost())
1048 WebGLBuffer* buffer = validateBufferDataParameters("bufferData", target, usage);
1052 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "bufferData", "size < 0");
1055 if (!isErrorGeneratedOnOutOfBoundsAccesses()) {
1056 if (!buffer->associateBufferData(static_cast<GC3Dsizeiptr>(size))) {
1057 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "bufferData", "invalid buffer");
1062 m_context->bufferData(target, static_cast<GC3Dsizeiptr>(size), usage);
1063 cleanupAfterGraphicsCall(false);
1066 void WebGLRenderingContext::bufferData(GC3Denum target, ArrayBuffer* data, GC3Denum usage, ExceptionCode& ec)
1069 if (isContextLost())
1071 WebGLBuffer* buffer = validateBufferDataParameters("bufferData", target, usage);
1075 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "bufferData", "no data");
1078 if (!isErrorGeneratedOnOutOfBoundsAccesses()) {
1079 if (!buffer->associateBufferData(data)) {
1080 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "bufferData", "invalid buffer");
1085 m_context->bufferData(target, data->byteLength(), data->data(), usage);
1086 cleanupAfterGraphicsCall(false);
1089 void WebGLRenderingContext::bufferData(GC3Denum target, ArrayBufferView* data, GC3Denum usage, ExceptionCode& ec)
1092 if (isContextLost())
1094 WebGLBuffer* buffer = validateBufferDataParameters("bufferData", target, usage);
1098 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "bufferData", "no data");
1101 if (!isErrorGeneratedOnOutOfBoundsAccesses()) {
1102 if (!buffer->associateBufferData(data)) {
1103 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "bufferData", "invalid buffer");
1108 m_context->bufferData(target, data->byteLength(), data->baseAddress(), usage);
1109 cleanupAfterGraphicsCall(false);
1112 void WebGLRenderingContext::bufferSubData(GC3Denum target, long long offset, ArrayBuffer* data, ExceptionCode& ec)
1115 if (isContextLost())
1117 WebGLBuffer* buffer = validateBufferDataParameters("bufferSubData", target, GraphicsContext3D::STATIC_DRAW);
1121 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "bufferSubData", "offset < 0");
1126 if (!isErrorGeneratedOnOutOfBoundsAccesses()) {
1127 if (!buffer->associateBufferSubData(static_cast<GC3Dintptr>(offset), data)) {
1128 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "bufferSubData", "offset out of range");
1133 m_context->bufferSubData(target, static_cast<GC3Dintptr>(offset), data->byteLength(), data->data());
1134 cleanupAfterGraphicsCall(false);
1137 void WebGLRenderingContext::bufferSubData(GC3Denum target, long long offset, ArrayBufferView* data, ExceptionCode& ec)
1140 if (isContextLost())
1142 WebGLBuffer* buffer = validateBufferDataParameters("bufferSubData", target, GraphicsContext3D::STATIC_DRAW);
1146 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "bufferSubData", "offset < 0");
1151 if (!isErrorGeneratedOnOutOfBoundsAccesses()) {
1152 if (!buffer->associateBufferSubData(static_cast<GC3Dintptr>(offset), data)) {
1153 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "bufferSubData", "offset out of range");
1158 m_context->bufferSubData(target, static_cast<GC3Dintptr>(offset), data->byteLength(), data->baseAddress());
1159 cleanupAfterGraphicsCall(false);
1162 GC3Denum WebGLRenderingContext::checkFramebufferStatus(GC3Denum target)
1164 if (isContextLost())
1165 return GraphicsContext3D::FRAMEBUFFER_UNSUPPORTED;
1166 if (target != GraphicsContext3D::FRAMEBUFFER) {
1167 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "checkFramebufferStatus", "invalid target");
1170 if (!m_framebufferBinding || !m_framebufferBinding->object())
1171 return GraphicsContext3D::FRAMEBUFFER_COMPLETE;
1172 const char* reason = "framebuffer incomplete";
1173 GC3Denum result = m_framebufferBinding->checkStatus(&reason);
1174 if (result != GraphicsContext3D::FRAMEBUFFER_COMPLETE) {
1175 printGLWarningToConsole("checkFramebufferStatus", reason);
1178 result = m_context->checkFramebufferStatus(target);
1179 cleanupAfterGraphicsCall(false);
1183 void WebGLRenderingContext::clear(GC3Dbitfield mask)
1185 if (isContextLost())
1187 if (mask & ~(GraphicsContext3D::COLOR_BUFFER_BIT | GraphicsContext3D::DEPTH_BUFFER_BIT | GraphicsContext3D::STENCIL_BUFFER_BIT)) {
1188 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "clear", "invalid mask");
1191 const char* reason = "framebuffer incomplete";
1192 if (m_framebufferBinding && !m_framebufferBinding->onAccess(graphicsContext3D(), !isResourceSafe(), &reason)) {
1193 synthesizeGLError(GraphicsContext3D::INVALID_FRAMEBUFFER_OPERATION, "clear", reason);
1196 if (!clearIfComposited(mask))
1197 m_context->clear(mask);
1198 cleanupAfterGraphicsCall(true);
1201 void WebGLRenderingContext::clearColor(GC3Dfloat r, GC3Dfloat g, GC3Dfloat b, GC3Dfloat a)
1203 if (isContextLost())
1213 m_clearColor[0] = r;
1214 m_clearColor[1] = g;
1215 m_clearColor[2] = b;
1216 m_clearColor[3] = a;
1217 m_context->clearColor(r, g, b, a);
1218 cleanupAfterGraphicsCall(false);
1221 void WebGLRenderingContext::clearDepth(GC3Dfloat depth)
1223 if (isContextLost())
1225 m_clearDepth = depth;
1226 m_context->clearDepth(depth);
1227 cleanupAfterGraphicsCall(false);
1230 void WebGLRenderingContext::clearStencil(GC3Dint s)
1232 if (isContextLost())
1235 m_context->clearStencil(s);
1236 cleanupAfterGraphicsCall(false);
1239 void WebGLRenderingContext::colorMask(GC3Dboolean red, GC3Dboolean green, GC3Dboolean blue, GC3Dboolean alpha)
1241 if (isContextLost())
1243 m_colorMask[0] = red;
1244 m_colorMask[1] = green;
1245 m_colorMask[2] = blue;
1246 m_colorMask[3] = alpha;
1247 m_context->colorMask(red, green, blue, alpha);
1248 cleanupAfterGraphicsCall(false);
1251 void WebGLRenderingContext::compileShader(WebGLShader* shader, ExceptionCode& ec)
1254 if (isContextLost() || !validateWebGLObject("compileShader", shader))
1256 m_context->compileShader(objectOrZero(shader));
1257 cleanupAfterGraphicsCall(false);
1260 void WebGLRenderingContext::compressedTexImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dsizei width,
1261 GC3Dsizei height, GC3Dint border, ArrayBufferView* data)
1263 if (isContextLost())
1265 if (!validateTexFuncLevel("compressedTexImage2D", target, level))
1268 if (!validateCompressedTexFormat(internalformat)) {
1269 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "compressedTexImage2D", "invalid internalformat");
1273 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "compressedTexImage2D", "border not 0");
1276 if (!validateCompressedTexDimensions("compressedTexImage2D", level, width, height, internalformat))
1278 if (!validateCompressedTexFuncData("compressedTexImage2D", width, height, internalformat, data))
1281 WebGLTexture* tex = validateTextureBinding("compressedTexImage2D", target, true);
1284 if (!isGLES2NPOTStrict()) {
1285 if (level && WebGLTexture::isNPOT(width, height)) {
1286 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "compressedTexImage2D", "level > 0 not power of 2");
1290 graphicsContext3D()->compressedTexImage2D(target, level, internalformat, width, height,
1291 border, data->byteLength(), data->baseAddress());
1292 tex->setLevelInfo(target, level, internalformat, width, height, GraphicsContext3D::UNSIGNED_BYTE);
1293 cleanupAfterGraphicsCall(false);
1296 void WebGLRenderingContext::compressedTexSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
1297 GC3Dsizei width, GC3Dsizei height, GC3Denum format, ArrayBufferView* data)
1299 if (isContextLost())
1301 if (!validateTexFuncLevel("compressedTexSubImage2D", target, level))
1303 if (!validateCompressedTexFormat(format)) {
1304 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "compressedTexSubImage2D", "invalid format");
1307 if (!validateCompressedTexFuncData("compressedTexSubImage2D", width, height, format, data))
1310 WebGLTexture* tex = validateTextureBinding("compressedTexSubImage2D", target, true);
1314 if (format != tex->getInternalFormat(target, level)) {
1315 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "compressedTexSubImage2D", "format does not match texture format");
1319 if (!validateCompressedTexSubDimensions("compressedTexSubImage2D", target, level, xoffset, yoffset, width, height, format, tex))
1322 graphicsContext3D()->compressedTexSubImage2D(target, level, xoffset, yoffset,
1323 width, height, format, data->byteLength(), data->baseAddress());
1324 cleanupAfterGraphicsCall(false);
1327 bool WebGLRenderingContext::validateSettableTexFormat(const char* functionName, GC3Denum format)
1329 if (GraphicsContext3D::getClearBitsByFormat(format) & (GraphicsContext3D::DEPTH_BUFFER_BIT | GraphicsContext3D::STENCIL_BUFFER_BIT)) {
1330 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "format can not be set, only rendered to");
1336 void WebGLRenderingContext::copyTexImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height, GC3Dint border)
1338 if (isContextLost())
1340 if (!validateTexFuncParameters("copyTexImage2D", NotTexSubImage2D, target, level, internalformat, width, height, border, internalformat, GraphicsContext3D::UNSIGNED_BYTE))
1342 if (!validateSettableTexFormat("copyTexImage2D", internalformat))
1344 WebGLTexture* tex = validateTextureBinding("copyTexImage2D", target, true);
1347 if (!isTexInternalFormatColorBufferCombinationValid(internalformat, getBoundFramebufferColorFormat())) {
1348 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "copyTexImage2D", "framebuffer is incompatible format");
1351 if (!isGLES2NPOTStrict() && level && WebGLTexture::isNPOT(width, height)) {
1352 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "copyTexImage2D", "level > 0 not power of 2");
1355 const char* reason = "framebuffer incomplete";
1356 if (m_framebufferBinding && !m_framebufferBinding->onAccess(graphicsContext3D(), !isResourceSafe(), &reason)) {
1357 synthesizeGLError(GraphicsContext3D::INVALID_FRAMEBUFFER_OPERATION, "copyTexImage2D", reason);
1360 clearIfComposited();
1361 if (isResourceSafe()) {
1362 ScopedDrawingBufferBinder binder(m_drawingBuffer.get(), m_framebufferBinding.get());
1363 m_context->copyTexImage2D(target, level, internalformat, x, y, width, height, border);
1365 ScopedDrawingBufferBinder binder(m_drawingBuffer.get(), m_framebufferBinding.get());
1366 GC3Dint clippedX, clippedY;
1367 GC3Dsizei clippedWidth, clippedHeight;
1368 if (clip2D(x, y, width, height, getBoundFramebufferWidth(), getBoundFramebufferHeight(), &clippedX, &clippedY, &clippedWidth, &clippedHeight)) {
1369 m_context->texImage2DResourceSafe(target, level, internalformat, width, height, border,
1370 internalformat, GraphicsContext3D::UNSIGNED_BYTE, m_unpackAlignment);
1371 if (clippedWidth > 0 && clippedHeight > 0) {
1372 m_context->copyTexSubImage2D(target, level, clippedX - x, clippedY - y,
1373 clippedX, clippedY, clippedWidth, clippedHeight);
1376 m_context->copyTexImage2D(target, level, internalformat, x, y, width, height, border);
1378 // FIXME: if the framebuffer is not complete, none of the below should be executed.
1379 tex->setLevelInfo(target, level, internalformat, width, height, GraphicsContext3D::UNSIGNED_BYTE);
1380 cleanupAfterGraphicsCall(false);
1383 void WebGLRenderingContext::copyTexSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height)
1385 if (isContextLost())
1387 if (!validateTexFuncLevel("copyTexSubImage2D", target, level))
1389 WebGLTexture* tex = validateTextureBinding("copyTexSubImage2D", target, true);
1392 if (!validateSize("copyTexSubImage2D", xoffset, yoffset) || !validateSize("copyTexSubImage2D", width, height))
1394 if (xoffset + width > tex->getWidth(target, level) || yoffset + height > tex->getHeight(target, level)) {
1395 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "copyTexSubImage2D", "rectangle out of range");
1398 GC3Denum internalformat = tex->getInternalFormat(target, level);
1399 if (!validateSettableTexFormat("copyTexSubImage2D", internalformat))
1401 if (!isTexInternalFormatColorBufferCombinationValid(internalformat, getBoundFramebufferColorFormat())) {
1402 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "copyTexSubImage2D", "framebuffer is incompatible format");
1405 const char* reason = "framebuffer incomplete";
1406 if (m_framebufferBinding && !m_framebufferBinding->onAccess(graphicsContext3D(), !isResourceSafe(), &reason)) {
1407 synthesizeGLError(GraphicsContext3D::INVALID_FRAMEBUFFER_OPERATION, "copyTexSubImage2D", reason);
1410 clearIfComposited();
1411 if (isResourceSafe()) {
1412 ScopedDrawingBufferBinder binder(m_drawingBuffer.get(), m_framebufferBinding.get());
1413 m_context->copyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height);
1415 GC3Dint clippedX, clippedY;
1416 GC3Dsizei clippedWidth, clippedHeight;
1417 if (clip2D(x, y, width, height, getBoundFramebufferWidth(), getBoundFramebufferHeight(), &clippedX, &clippedY, &clippedWidth, &clippedHeight)) {
1418 GC3Denum format = tex->getInternalFormat(target, level);
1419 GC3Denum type = tex->getType(target, level);
1420 OwnArrayPtr<unsigned char> zero;
1421 if (width && height) {
1423 GC3Denum error = m_context->computeImageSizeInBytes(format, type, width, height, m_unpackAlignment, &size, 0);
1424 if (error != GraphicsContext3D::NO_ERROR) {
1425 synthesizeGLError(error, "copyTexSubImage2D", "bad dimensions");
1428 zero = adoptArrayPtr(new unsigned char[size]);
1430 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "copyTexSubImage2D", "out of memory");
1433 memset(zero.get(), 0, size);
1435 m_context->texSubImage2D(target, level, xoffset, yoffset, width, height, format, type, zero.get());
1436 if (clippedWidth > 0 && clippedHeight > 0) {
1437 ScopedDrawingBufferBinder binder(m_drawingBuffer.get(), m_framebufferBinding.get());
1438 m_context->copyTexSubImage2D(target, level, xoffset + clippedX - x, yoffset + clippedY - y,
1439 clippedX, clippedY, clippedWidth, clippedHeight);
1442 ScopedDrawingBufferBinder binder(m_drawingBuffer.get(), m_framebufferBinding.get());
1443 m_context->copyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height);
1446 cleanupAfterGraphicsCall(false);
1449 PassRefPtr<WebGLBuffer> WebGLRenderingContext::createBuffer()
1451 if (isContextLost())
1453 RefPtr<WebGLBuffer> o = WebGLBuffer::create(this);
1454 addSharedObject(o.get());
1458 PassRefPtr<WebGLFramebuffer> WebGLRenderingContext::createFramebuffer()
1460 if (isContextLost())
1462 RefPtr<WebGLFramebuffer> o = WebGLFramebuffer::create(this);
1463 addContextObject(o.get());
1467 PassRefPtr<WebGLTexture> WebGLRenderingContext::createTexture()
1469 if (isContextLost())
1471 RefPtr<WebGLTexture> o = WebGLTexture::create(this);
1472 addSharedObject(o.get());
1476 PassRefPtr<WebGLProgram> WebGLRenderingContext::createProgram()
1478 if (isContextLost())
1480 RefPtr<WebGLProgram> o = WebGLProgram::create(this);
1481 addSharedObject(o.get());
1485 PassRefPtr<WebGLRenderbuffer> WebGLRenderingContext::createRenderbuffer()
1487 if (isContextLost())
1489 RefPtr<WebGLRenderbuffer> o = WebGLRenderbuffer::create(this);
1490 addSharedObject(o.get());
1494 PassRefPtr<WebGLShader> WebGLRenderingContext::createShader(GC3Denum type, ExceptionCode& ec)
1497 if (isContextLost())
1499 if (type != GraphicsContext3D::VERTEX_SHADER && type != GraphicsContext3D::FRAGMENT_SHADER) {
1500 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "createShader", "invalid shader type");
1504 RefPtr<WebGLShader> o = WebGLShader::create(this, type);
1505 addSharedObject(o.get());
1509 void WebGLRenderingContext::cullFace(GC3Denum mode)
1511 if (isContextLost())
1513 m_context->cullFace(mode);
1514 cleanupAfterGraphicsCall(false);
1517 bool WebGLRenderingContext::deleteObject(WebGLObject* object)
1519 if (isContextLost() || !object)
1521 if (!object->validate(contextGroup(), this)) {
1522 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "delete", "object does not belong to this context");
1525 if (object->object())
1526 // We need to pass in context here because we want
1527 // things in this context unbound.
1528 object->deleteObject(graphicsContext3D());
1532 void WebGLRenderingContext::deleteBuffer(WebGLBuffer* buffer)
1534 if (!deleteObject(buffer))
1536 if (m_boundArrayBuffer == buffer)
1537 m_boundArrayBuffer = 0;
1538 RefPtr<WebGLBuffer> elementArrayBuffer = m_boundVertexArrayObject->getElementArrayBuffer();
1539 if (elementArrayBuffer == buffer)
1540 m_boundVertexArrayObject->setElementArrayBuffer(0);
1541 if (!isGLES2Compliant()) {
1542 WebGLVertexArrayObjectOES::VertexAttribState& state = m_boundVertexArrayObject->getVertexAttribState(0);
1543 if (buffer == state.bufferBinding) {
1544 state.bufferBinding = m_vertexAttrib0Buffer;
1545 state.bytesPerElement = 0;
1547 state.type = GraphicsContext3D::FLOAT;
1548 state.normalized = false;
1550 state.originalStride = 0;
1556 void WebGLRenderingContext::deleteFramebuffer(WebGLFramebuffer* framebuffer)
1558 if (!deleteObject(framebuffer))
1560 if (framebuffer == m_framebufferBinding) {
1561 m_framebufferBinding = 0;
1562 if (m_drawingBuffer) {
1563 m_drawingBuffer->setFramebufferBinding(0);
1564 // Have to call bindFramebuffer here to bind back to internal fbo.
1565 m_drawingBuffer->bind();
1567 m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, 0);
1571 void WebGLRenderingContext::deleteProgram(WebGLProgram* program)
1573 deleteObject(program);
1574 // We don't reset m_currentProgram to 0 here because the deletion of the
1575 // current program is delayed.
1578 void WebGLRenderingContext::deleteRenderbuffer(WebGLRenderbuffer* renderbuffer)
1580 if (!deleteObject(renderbuffer))
1582 if (renderbuffer == m_renderbufferBinding)
1583 m_renderbufferBinding = 0;
1584 if (m_framebufferBinding)
1585 m_framebufferBinding->removeAttachmentFromBoundFramebuffer(renderbuffer);
1588 void WebGLRenderingContext::deleteShader(WebGLShader* shader)
1590 deleteObject(shader);
1593 void WebGLRenderingContext::deleteTexture(WebGLTexture* texture)
1595 if (!deleteObject(texture))
1597 for (size_t i = 0; i < m_textureUnits.size(); ++i) {
1598 if (texture == m_textureUnits[i].m_texture2DBinding)
1599 m_textureUnits[i].m_texture2DBinding = 0;
1600 if (texture == m_textureUnits[i].m_textureCubeMapBinding)
1601 m_textureUnits[i].m_textureCubeMapBinding = 0;
1603 if (m_framebufferBinding)
1604 m_framebufferBinding->removeAttachmentFromBoundFramebuffer(texture);
1607 void WebGLRenderingContext::depthFunc(GC3Denum func)
1609 if (isContextLost())
1611 m_context->depthFunc(func);
1612 cleanupAfterGraphicsCall(false);
1615 void WebGLRenderingContext::depthMask(GC3Dboolean flag)
1617 if (isContextLost())
1620 m_context->depthMask(flag);
1621 cleanupAfterGraphicsCall(false);
1624 void WebGLRenderingContext::depthRange(GC3Dfloat zNear, GC3Dfloat zFar)
1626 if (isContextLost())
1629 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "depthRange", "zNear > zFar");
1632 m_context->depthRange(zNear, zFar);
1633 cleanupAfterGraphicsCall(false);
1636 void WebGLRenderingContext::detachShader(WebGLProgram* program, WebGLShader* shader, ExceptionCode& ec)
1639 if (isContextLost() || !validateWebGLObject("detachShader", program) || !validateWebGLObject("detachShader", shader))
1641 if (!program->detachShader(shader)) {
1642 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "detachShader", "shader not attached");
1645 m_context->detachShader(objectOrZero(program), objectOrZero(shader));
1646 shader->onDetached(graphicsContext3D());
1647 cleanupAfterGraphicsCall(false);
1650 void WebGLRenderingContext::disable(GC3Denum cap)
1652 if (isContextLost() || !validateCapability("disable", cap))
1654 if (cap == GraphicsContext3D::STENCIL_TEST) {
1655 m_stencilEnabled = false;
1657 cleanupAfterGraphicsCall(false);
1660 if (cap == GraphicsContext3D::SCISSOR_TEST) {
1661 m_scissorEnabled = false;
1662 if (m_drawingBuffer)
1663 m_drawingBuffer->setScissorEnabled(m_scissorEnabled);
1665 m_context->disable(cap);
1666 cleanupAfterGraphicsCall(false);
1669 void WebGLRenderingContext::disableVertexAttribArray(GC3Duint index, ExceptionCode& ec)
1672 if (isContextLost())
1674 if (index >= m_maxVertexAttribs) {
1675 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "disableVertexAttribArray", "index out of range");
1679 WebGLVertexArrayObjectOES::VertexAttribState& state = m_boundVertexArrayObject->getVertexAttribState(index);
1680 state.enabled = false;
1682 if (index > 0 || isGLES2Compliant()) {
1683 m_context->disableVertexAttribArray(index);
1684 cleanupAfterGraphicsCall(false);
1688 bool WebGLRenderingContext::validateElementArraySize(GC3Dsizei count, GC3Denum type, GC3Dintptr offset)
1690 RefPtr<WebGLBuffer> elementArrayBuffer = m_boundVertexArrayObject->getElementArrayBuffer();
1692 if (!elementArrayBuffer)
1698 if (type == GraphicsContext3D::UNSIGNED_SHORT) {
1699 // For an unsigned short array, offset must be divisible by 2 for alignment reasons.
1703 // Make uoffset an element offset.
1706 GC3Dsizeiptr n = elementArrayBuffer->byteLength() / 2;
1707 if (offset > n || count > n - offset)
1709 } else if (type == GraphicsContext3D::UNSIGNED_BYTE) {
1710 GC3Dsizeiptr n = elementArrayBuffer->byteLength();
1711 if (offset > n || count > n - offset)
1717 bool WebGLRenderingContext::validateIndexArrayConservative(GC3Denum type, int& numElementsRequired)
1719 // Performs conservative validation by caching a maximum index of
1720 // the given type per element array buffer. If all of the bound
1721 // array buffers have enough elements to satisfy that maximum
1722 // index, skips the expensive per-draw-call iteration in
1723 // validateIndexArrayPrecise.
1725 RefPtr<WebGLBuffer> elementArrayBuffer = m_boundVertexArrayObject->getElementArrayBuffer();
1727 if (!elementArrayBuffer)
1730 GC3Dsizeiptr numElements = elementArrayBuffer->byteLength();
1731 // The case count==0 is already dealt with in drawElements before validateIndexArrayConservative.
1734 const ArrayBuffer* buffer = elementArrayBuffer->elementArrayBuffer();
1737 int maxIndex = elementArrayBuffer->getCachedMaxIndex(type);
1739 // Compute the maximum index in the entire buffer for the given type of index.
1741 case GraphicsContext3D::UNSIGNED_BYTE: {
1742 const GC3Dubyte* p = static_cast<const GC3Dubyte*>(buffer->data());
1743 for (GC3Dsizeiptr i = 0; i < numElements; i++)
1744 maxIndex = max(maxIndex, static_cast<int>(p[i]));
1747 case GraphicsContext3D::UNSIGNED_SHORT: {
1748 numElements /= sizeof(GC3Dushort);
1749 const GC3Dushort* p = static_cast<const GC3Dushort*>(buffer->data());
1750 for (GC3Dsizeiptr i = 0; i < numElements; i++)
1751 maxIndex = max(maxIndex, static_cast<int>(p[i]));
1757 elementArrayBuffer->setCachedMaxIndex(type, maxIndex);
1760 if (maxIndex >= 0) {
1761 // The number of required elements is one more than the maximum
1762 // index that will be accessed.
1763 numElementsRequired = maxIndex + 1;
1770 bool WebGLRenderingContext::validateIndexArrayPrecise(GC3Dsizei count, GC3Denum type, GC3Dintptr offset, int& numElementsRequired)
1772 ASSERT(count >= 0 && offset >= 0);
1775 RefPtr<WebGLBuffer> elementArrayBuffer = m_boundVertexArrayObject->getElementArrayBuffer();
1777 if (!elementArrayBuffer)
1781 numElementsRequired = 0;
1785 if (!elementArrayBuffer->elementArrayBuffer())
1788 unsigned long uoffset = offset;
1789 unsigned long n = count;
1791 if (type == GraphicsContext3D::UNSIGNED_SHORT) {
1792 // Make uoffset an element offset.
1793 uoffset /= sizeof(GC3Dushort);
1794 const GC3Dushort* p = static_cast<const GC3Dushort*>(elementArrayBuffer->elementArrayBuffer()->data()) + uoffset;
1800 } else if (type == GraphicsContext3D::UNSIGNED_BYTE) {
1801 const GC3Dubyte* p = static_cast<const GC3Dubyte*>(elementArrayBuffer->elementArrayBuffer()->data()) + uoffset;
1809 // Then set the last index in the index array and make sure it is valid.
1810 numElementsRequired = lastIndex + 1;
1811 return numElementsRequired > 0;
1814 bool WebGLRenderingContext::validateRenderingState(int numElementsRequired)
1816 if (!m_currentProgram)
1819 // Look in each enabled vertex attrib and check if they've been bound to a buffer.
1820 for (unsigned i = 0; i < m_maxVertexAttribs; ++i) {
1821 const WebGLVertexArrayObjectOES::VertexAttribState& state = m_boundVertexArrayObject->getVertexAttribState(i);
1823 && (!state.bufferBinding || !state.bufferBinding->object()))
1827 if (numElementsRequired <= 0)
1830 // Look in each consumed vertex attrib (by the current program) and find the smallest buffer size
1831 int smallestNumElements = INT_MAX;
1832 int numActiveAttribLocations = m_currentProgram->numActiveAttribLocations();
1833 for (int i = 0; i < numActiveAttribLocations; ++i) {
1834 int loc = m_currentProgram->getActiveAttribLocation(i);
1835 if (loc >= 0 && loc < static_cast<int>(m_maxVertexAttribs)) {
1836 const WebGLVertexArrayObjectOES::VertexAttribState& state = m_boundVertexArrayObject->getVertexAttribState(loc);
1837 if (state.enabled) {
1838 // Avoid off-by-one errors in numElements computation.
1839 // For the last element, we will only touch the data for the
1840 // element and nothing beyond it.
1841 int bytesRemaining = static_cast<int>(state.bufferBinding->byteLength() - state.offset);
1842 int numElements = 0;
1843 ASSERT(state.stride > 0);
1844 if (bytesRemaining >= state.bytesPerElement)
1845 numElements = 1 + (bytesRemaining - state.bytesPerElement) / state.stride;
1846 if (numElements < smallestNumElements)
1847 smallestNumElements = numElements;
1852 if (smallestNumElements == INT_MAX)
1853 smallestNumElements = 0;
1855 return numElementsRequired <= smallestNumElements;
1858 bool WebGLRenderingContext::validateWebGLObject(const char* functionName, WebGLObject* object)
1860 if (!object || !object->object()) {
1861 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "no object or object deleted");
1864 if (!object->validate(contextGroup(), this)) {
1865 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "object does not belong to this context");
1871 void WebGLRenderingContext::drawArrays(GC3Denum mode, GC3Dint first, GC3Dsizei count, ExceptionCode& ec)
1875 if (isContextLost() || !validateDrawMode("drawArrays", mode))
1878 if (!validateStencilSettings("drawArrays"))
1881 if (first < 0 || count < 0) {
1882 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "drawArrays", "first or count < 0");
1887 cleanupAfterGraphicsCall(true);
1891 if (!isErrorGeneratedOnOutOfBoundsAccesses()) {
1892 // Ensure we have a valid rendering state
1893 CheckedInt<GC3Dint> checkedFirst(first);
1894 CheckedInt<GC3Dint> checkedCount(count);
1895 CheckedInt<GC3Dint> checkedSum = checkedFirst + checkedCount;
1896 if (!checkedSum.valid() || !validateRenderingState(checkedSum.value())) {
1897 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "drawArrays", "attempt to access out of bounds arrays");
1901 if (!validateRenderingState(0)) {
1902 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "drawArrays", "attribs not setup correctly");
1907 const char* reason = "framebuffer incomplete";
1908 if (m_framebufferBinding && !m_framebufferBinding->onAccess(graphicsContext3D(), !isResourceSafe(), &reason)) {
1909 synthesizeGLError(GraphicsContext3D::INVALID_FRAMEBUFFER_OPERATION, "drawArrays", reason);
1913 clearIfComposited();
1915 bool vertexAttrib0Simulated = false;
1916 if (!isGLES2Compliant())
1917 vertexAttrib0Simulated = simulateVertexAttrib0(first + count - 1);
1918 if (!isGLES2NPOTStrict())
1919 handleNPOTTextures(true);
1920 m_context->drawArrays(mode, first, count);
1921 if (!isGLES2Compliant() && vertexAttrib0Simulated)
1922 restoreStatesAfterVertexAttrib0Simulation();
1923 if (!isGLES2NPOTStrict())
1924 handleNPOTTextures(false);
1925 cleanupAfterGraphicsCall(true);
1928 void WebGLRenderingContext::drawElements(GC3Denum mode, GC3Dsizei count, GC3Denum type, long long offset, ExceptionCode& ec)
1932 if (isContextLost() || !validateDrawMode("drawElements", mode))
1935 if (!validateStencilSettings("drawElements"))
1939 case GraphicsContext3D::UNSIGNED_BYTE:
1940 case GraphicsContext3D::UNSIGNED_SHORT:
1943 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "drawElements", "invalid type");
1947 if (count < 0 || offset < 0) {
1948 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "drawElements", "count or offset < 0");
1953 cleanupAfterGraphicsCall(true);
1957 if (!m_boundVertexArrayObject->getElementArrayBuffer()) {
1958 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "drawElements", "no ELEMENT_ARRAY_BUFFER bound");
1962 int numElements = 0;
1963 if (!isErrorGeneratedOnOutOfBoundsAccesses()) {
1964 // Ensure we have a valid rendering state
1965 if (!validateElementArraySize(count, type, static_cast<GC3Dintptr>(offset))) {
1966 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "drawElements", "request out of bounds for current ELEMENT_ARRAY_BUFFER");
1971 if (!validateIndexArrayConservative(type, numElements) || !validateRenderingState(numElements)) {
1972 if (!validateIndexArrayPrecise(count, type, static_cast<GC3Dintptr>(offset), numElements) || !validateRenderingState(numElements)) {
1973 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "drawElements", "attempt to access out of bounds arrays");
1978 if (!validateRenderingState(0)) {
1979 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "drawElements", "attribs not setup correctly");
1984 const char* reason = "framebuffer incomplete";
1985 if (m_framebufferBinding && !m_framebufferBinding->onAccess(graphicsContext3D(), !isResourceSafe(), &reason)) {
1986 synthesizeGLError(GraphicsContext3D::INVALID_FRAMEBUFFER_OPERATION, "drawElements", reason);
1989 clearIfComposited();
1991 bool vertexAttrib0Simulated = false;
1992 if (!isGLES2Compliant()) {
1994 validateIndexArrayPrecise(count, type, static_cast<GC3Dintptr>(offset), numElements);
1995 vertexAttrib0Simulated = simulateVertexAttrib0(numElements);
1997 if (!isGLES2NPOTStrict())
1998 handleNPOTTextures(true);
1999 m_context->drawElements(mode, count, type, static_cast<GC3Dintptr>(offset));
2000 if (!isGLES2Compliant() && vertexAttrib0Simulated)
2001 restoreStatesAfterVertexAttrib0Simulation();
2002 if (!isGLES2NPOTStrict())
2003 handleNPOTTextures(false);
2004 cleanupAfterGraphicsCall(true);
2007 void WebGLRenderingContext::enable(GC3Denum cap)
2009 if (isContextLost() || !validateCapability("enable", cap))
2011 if (cap == GraphicsContext3D::STENCIL_TEST) {
2012 m_stencilEnabled = true;
2014 cleanupAfterGraphicsCall(false);
2017 if (cap == GraphicsContext3D::SCISSOR_TEST) {
2018 m_scissorEnabled = true;
2019 if (m_drawingBuffer)
2020 m_drawingBuffer->setScissorEnabled(m_scissorEnabled);
2022 m_context->enable(cap);
2023 cleanupAfterGraphicsCall(false);
2026 void WebGLRenderingContext::enableVertexAttribArray(GC3Duint index, ExceptionCode& ec)
2029 if (isContextLost())
2031 if (index >= m_maxVertexAttribs) {
2032 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "enableVertexAttribArray", "index out of range");
2036 WebGLVertexArrayObjectOES::VertexAttribState& state = m_boundVertexArrayObject->getVertexAttribState(index);
2037 state.enabled = true;
2039 m_context->enableVertexAttribArray(index);
2040 cleanupAfterGraphicsCall(false);
2043 void WebGLRenderingContext::finish()
2045 if (isContextLost())
2047 m_context->finish();
2048 cleanupAfterGraphicsCall(false);
2051 void WebGLRenderingContext::flush()
2053 if (isContextLost())
2056 cleanupAfterGraphicsCall(false);
2059 void WebGLRenderingContext::framebufferRenderbuffer(GC3Denum target, GC3Denum attachment, GC3Denum renderbuffertarget, WebGLRenderbuffer* buffer, ExceptionCode& ec)
2062 if (isContextLost() || !validateFramebufferFuncParameters("framebufferRenderbuffer", target, attachment))
2064 if (renderbuffertarget != GraphicsContext3D::RENDERBUFFER) {
2065 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "framebufferRenderbuffer", "invalid target");
2068 if (buffer && !buffer->validate(contextGroup(), this)) {
2069 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "framebufferRenderbuffer", "no buffer or buffer not from this context");
2072 // Don't allow the default framebuffer to be mutated; all current
2073 // implementations use an FBO internally in place of the default
2075 if (!m_framebufferBinding || !m_framebufferBinding->object()) {
2076 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "framebufferRenderbuffer", "no framebuffer bound");
2079 Platform3DObject bufferObject = objectOrZero(buffer);
2080 switch (attachment) {
2081 case GraphicsContext3D::DEPTH_STENCIL_ATTACHMENT:
2082 m_context->framebufferRenderbuffer(target, GraphicsContext3D::DEPTH_ATTACHMENT, renderbuffertarget, bufferObject);
2083 m_context->framebufferRenderbuffer(target, GraphicsContext3D::STENCIL_ATTACHMENT, renderbuffertarget, bufferObject);
2085 case GraphicsContext3D::DEPTH_ATTACHMENT:
2086 m_context->framebufferRenderbuffer(target, attachment, renderbuffertarget, bufferObject);
2088 case GraphicsContext3D::STENCIL_ATTACHMENT:
2089 m_context->framebufferRenderbuffer(target, attachment, renderbuffertarget, bufferObject);
2092 m_context->framebufferRenderbuffer(target, attachment, renderbuffertarget, bufferObject);
2094 m_framebufferBinding->setAttachmentForBoundFramebuffer(attachment, buffer);
2096 cleanupAfterGraphicsCall(false);
2099 void WebGLRenderingContext::framebufferTexture2D(GC3Denum target, GC3Denum attachment, GC3Denum textarget, WebGLTexture* texture, GC3Dint level, ExceptionCode& ec)
2102 if (isContextLost() || !validateFramebufferFuncParameters("framebufferTexture2D", target, attachment))
2105 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "framebufferTexture2D", "level not 0");
2108 if (texture && !texture->validate(contextGroup(), this)) {
2109 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "framebufferTexture2D", "no texture or texture not from this context");
2112 // Don't allow the default framebuffer to be mutated; all current
2113 // implementations use an FBO internally in place of the default
2115 if (!m_framebufferBinding || !m_framebufferBinding->object()) {
2116 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "framebufferTexture2D", "no framebuffer bound");
2119 Platform3DObject textureObject = objectOrZero(texture);
2120 switch (attachment) {
2121 case GraphicsContext3D::DEPTH_STENCIL_ATTACHMENT:
2122 m_context->framebufferTexture2D(target, GraphicsContext3D::DEPTH_ATTACHMENT, textarget, textureObject, level);
2123 m_context->framebufferTexture2D(target, GraphicsContext3D::STENCIL_ATTACHMENT, textarget, textureObject, level);
2125 case GraphicsContext3D::DEPTH_ATTACHMENT:
2126 m_context->framebufferTexture2D(target, attachment, textarget, textureObject, level);
2128 case GraphicsContext3D::STENCIL_ATTACHMENT:
2129 m_context->framebufferTexture2D(target, attachment, textarget, textureObject, level);
2132 m_context->framebufferTexture2D(target, attachment, textarget, textureObject, level);
2134 m_framebufferBinding->setAttachmentForBoundFramebuffer(attachment, textarget, texture, level);
2136 cleanupAfterGraphicsCall(false);
2139 void WebGLRenderingContext::frontFace(GC3Denum mode)
2141 if (isContextLost())
2143 m_context->frontFace(mode);
2144 cleanupAfterGraphicsCall(false);
2147 void WebGLRenderingContext::generateMipmap(GC3Denum target)
2149 if (isContextLost())
2151 WebGLTexture* tex = validateTextureBinding("generateMipmap", target, false);
2154 if (!tex->canGenerateMipmaps()) {
2155 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "generateMipmap", "level 0 not power of 2 or not all the same size");
2158 if (!validateSettableTexFormat("generateMipmap", tex->getInternalFormat(target, 0)))
2161 // generateMipmap won't work properly if minFilter is not NEAREST_MIPMAP_LINEAR
2162 // on Mac. Remove the hack once this driver bug is fixed.
2164 bool needToResetMinFilter = false;
2165 if (tex->getMinFilter() != GraphicsContext3D::NEAREST_MIPMAP_LINEAR) {
2166 m_context->texParameteri(target, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::NEAREST_MIPMAP_LINEAR);
2167 needToResetMinFilter = true;
2170 m_context->generateMipmap(target);
2172 if (needToResetMinFilter)
2173 m_context->texParameteri(target, GraphicsContext3D::TEXTURE_MIN_FILTER, tex->getMinFilter());
2175 tex->generateMipmapLevelInfo();
2176 cleanupAfterGraphicsCall(false);
2179 PassRefPtr<WebGLActiveInfo> WebGLRenderingContext::getActiveAttrib(WebGLProgram* program, GC3Duint index, ExceptionCode& ec)
2182 if (isContextLost() || !validateWebGLObject("getActiveAttrib", program))
2185 if (!m_context->getActiveAttrib(objectOrZero(program), index, info))
2187 return WebGLActiveInfo::create(info.name, info.type, info.size);
2190 PassRefPtr<WebGLActiveInfo> WebGLRenderingContext::getActiveUniform(WebGLProgram* program, GC3Duint index, ExceptionCode& ec)
2193 if (isContextLost() || !validateWebGLObject("getActiveUniform", program))
2196 if (!m_context->getActiveUniform(objectOrZero(program), index, info))
2198 if (!isGLES2Compliant())
2199 if (info.size > 1 && !info.name.endsWith("[0]"))
2200 info.name.append("[0]");
2201 return WebGLActiveInfo::create(info.name, info.type, info.size);
2204 bool WebGLRenderingContext::getAttachedShaders(WebGLProgram* program, Vector<RefPtr<WebGLShader> >& shaderObjects, ExceptionCode& ec)
2207 shaderObjects.clear();
2208 if (isContextLost() || !validateWebGLObject("getAttachedShaders", program))
2211 const GC3Denum shaderType[] = {
2212 GraphicsContext3D::VERTEX_SHADER,
2213 GraphicsContext3D::FRAGMENT_SHADER
2215 for (unsigned i = 0; i < sizeof(shaderType) / sizeof(GC3Denum); ++i) {
2216 WebGLShader* shader = program->getAttachedShader(shaderType[i]);
2218 shaderObjects.append(shader);
2223 GC3Dint WebGLRenderingContext::getAttribLocation(WebGLProgram* program, const String& name)
2225 if (isContextLost() || !validateWebGLObject("getAttribLocation", program))
2227 if (!validateLocationLength("getAttribLocation", name))
2229 if (!validateString("getAttribLocation", name))
2231 if (isPrefixReserved(name))
2233 if (!program->getLinkStatus()) {
2234 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "getAttribLocation", "program not linked");
2237 return m_context->getAttribLocation(objectOrZero(program), name);
2240 WebGLGetInfo WebGLRenderingContext::getBufferParameter(GC3Denum target, GC3Denum pname, ExceptionCode& ec)
2243 if (isContextLost())
2244 return WebGLGetInfo();
2245 if (target != GraphicsContext3D::ARRAY_BUFFER && target != GraphicsContext3D::ELEMENT_ARRAY_BUFFER) {
2246 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getBufferParameter", "invalid target");
2247 return WebGLGetInfo();
2250 if (pname != GraphicsContext3D::BUFFER_SIZE && pname != GraphicsContext3D::BUFFER_USAGE) {
2251 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getBufferParameter", "invalid parameter name");
2252 return WebGLGetInfo();
2255 WebGLStateRestorer(this, false);
2257 m_context->getBufferParameteriv(target, pname, &value);
2258 if (pname == GraphicsContext3D::BUFFER_SIZE)
2259 return WebGLGetInfo(value);
2260 return WebGLGetInfo(static_cast<unsigned int>(value));
2263 PassRefPtr<WebGLContextAttributes> WebGLRenderingContext::getContextAttributes()
2265 if (isContextLost())
2267 // We always need to return a new WebGLContextAttributes object to
2268 // prevent the user from mutating any cached version.
2270 // Also, we need to enforce requested values of "false" for depth
2271 // and stencil, regardless of the properties of the underlying
2272 // GraphicsContext3D.
2273 RefPtr<WebGLContextAttributes> attributes = WebGLContextAttributes::create(m_context->getContextAttributes());
2274 if (!m_attributes.depth)
2275 attributes->setDepth(false);
2276 if (!m_attributes.stencil)
2277 attributes->setStencil(false);
2278 return attributes.release();
2281 GC3Denum WebGLRenderingContext::getError()
2283 return m_context->getError();
2286 WebGLExtension* WebGLRenderingContext::getExtension(const String& name)
2288 if (isContextLost())
2291 if (equalIgnoringCase(name, "WEBKIT_EXT_texture_filter_anisotropic")
2292 && m_context->getExtensions()->supports("GL_EXT_texture_filter_anisotropic")) {
2293 if (!m_extTextureFilterAnisotropic) {
2294 m_context->getExtensions()->ensureEnabled("GL_EXT_texture_filter_anisotropic");
2295 m_extTextureFilterAnisotropic = EXTTextureFilterAnisotropic::create(this);
2297 return m_extTextureFilterAnisotropic.get();
2299 if (equalIgnoringCase(name, "OES_standard_derivatives")
2300 && m_context->getExtensions()->supports("GL_OES_standard_derivatives")) {
2301 if (!m_oesStandardDerivatives) {
2302 m_context->getExtensions()->ensureEnabled("GL_OES_standard_derivatives");
2303 m_oesStandardDerivatives = OESStandardDerivatives::create(this);
2305 return m_oesStandardDerivatives.get();
2307 if (equalIgnoringCase(name, "OES_texture_float")
2308 && m_context->getExtensions()->supports("GL_OES_texture_float")) {
2309 if (!m_oesTextureFloat) {
2310 m_context->getExtensions()->ensureEnabled("GL_OES_texture_float");
2311 m_oesTextureFloat = OESTextureFloat::create(this);
2313 return m_oesTextureFloat.get();
2315 if (equalIgnoringCase(name, "OES_vertex_array_object")
2316 && m_context->getExtensions()->supports("GL_OES_vertex_array_object")) {
2317 if (!m_oesVertexArrayObject) {
2318 m_context->getExtensions()->ensureEnabled("GL_OES_vertex_array_object");
2319 m_oesVertexArrayObject = OESVertexArrayObject::create(this);
2321 return m_oesVertexArrayObject.get();
2323 if (equalIgnoringCase(name, "WEBKIT_WEBGL_lose_context")
2324 // FIXME: remove this after a certain grace period.
2325 || equalIgnoringCase(name, "WEBKIT_lose_context")) {
2326 if (!m_webglLoseContext)
2327 m_webglLoseContext = WebGLLoseContext::create(this);
2328 return m_webglLoseContext.get();
2330 if (equalIgnoringCase(name, "WEBKIT_WEBGL_compressed_texture_s3tc")) {
2331 // Use WEBKIT_ prefix until extension is official.
2332 if (!m_webglCompressedTextureS3TC)
2333 m_webglCompressedTextureS3TC = WebGLCompressedTextureS3TC::create(this);
2334 return m_webglCompressedTextureS3TC.get();
2336 if (equalIgnoringCase(name, "WEBKIT_WEBGL_depth_texture")
2337 && WebGLDepthTexture::supported(graphicsContext3D())) {
2338 if (!m_webglDepthTexture) {
2339 m_context->getExtensions()->ensureEnabled("GL_CHROMIUM_depth_texture");
2340 m_webglDepthTexture = WebGLDepthTexture::create(this);
2342 return m_webglDepthTexture.get();
2344 if (allowPrivilegedExtensions()) {
2345 if (equalIgnoringCase(name, "WEBGL_debug_renderer_info")) {
2346 if (!m_webglDebugRendererInfo)
2347 m_webglDebugRendererInfo = WebGLDebugRendererInfo::create(this);
2348 return m_webglDebugRendererInfo.get();
2350 if (equalIgnoringCase(name, "WEBGL_debug_shaders")
2351 && m_context->getExtensions()->supports("GL_ANGLE_translated_shader_source")) {
2352 if (!m_webglDebugShaders)
2353 m_webglDebugShaders = WebGLDebugShaders::create(this);
2354 return m_webglDebugShaders.get();
2361 WebGLGetInfo WebGLRenderingContext::getFramebufferAttachmentParameter(GC3Denum target, GC3Denum attachment, GC3Denum pname, ExceptionCode& ec)
2364 if (isContextLost() || !validateFramebufferFuncParameters("getFramebufferAttachmentParameter", target, attachment))
2365 return WebGLGetInfo();
2367 if (!m_framebufferBinding || !m_framebufferBinding->object()) {
2368 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "getFramebufferAttachmentParameter", "no framebuffer bound");
2369 return WebGLGetInfo();
2372 WebGLSharedObject* object = m_framebufferBinding->getAttachmentObject(attachment);
2374 if (pname == GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE)
2375 return WebGLGetInfo(GraphicsContext3D::NONE);
2376 // OpenGL ES 2.0 specifies INVALID_ENUM in this case, while desktop GL
2377 // specifies INVALID_OPERATION.
2378 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getFramebufferAttachmentParameter", "invalid parameter name");
2379 return WebGLGetInfo();
2382 ASSERT(object->isTexture() || object->isRenderbuffer());
2383 if (object->isTexture()) {
2385 case GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
2386 return WebGLGetInfo(GraphicsContext3D::TEXTURE);
2387 case GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
2388 return WebGLGetInfo(PassRefPtr<WebGLTexture>(reinterpret_cast<WebGLTexture*>(object)));
2389 case GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
2390 case GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
2392 WebGLStateRestorer(this, false);
2394 m_context->getFramebufferAttachmentParameteriv(target, attachment, pname, &value);
2395 return WebGLGetInfo(value);
2398 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getFramebufferAttachmentParameter", "invalid parameter name for texture attachment");
2399 return WebGLGetInfo();
2403 case GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
2404 return WebGLGetInfo(GraphicsContext3D::RENDERBUFFER);
2405 case GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
2406 return WebGLGetInfo(PassRefPtr<WebGLRenderbuffer>(reinterpret_cast<WebGLRenderbuffer*>(object)));
2408 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getFramebufferAttachmentParameter", "invalid parameter name for renderbuffer attachment");
2409 return WebGLGetInfo();
2414 WebGLGetInfo WebGLRenderingContext::getParameter(GC3Denum pname, ExceptionCode& ec)
2417 if (isContextLost())
2418 return WebGLGetInfo();
2419 const int intZero = 0;
2420 WebGLStateRestorer(this, false);
2422 case GraphicsContext3D::ACTIVE_TEXTURE:
2423 return getUnsignedIntParameter(pname);
2424 case GraphicsContext3D::ALIASED_LINE_WIDTH_RANGE:
2425 return getWebGLFloatArrayParameter(pname);
2426 case GraphicsContext3D::ALIASED_POINT_SIZE_RANGE:
2427 return getWebGLFloatArrayParameter(pname);
2428 case GraphicsContext3D::ALPHA_BITS:
2429 return getIntParameter(pname);
2430 case GraphicsContext3D::ARRAY_BUFFER_BINDING:
2431 return WebGLGetInfo(PassRefPtr<WebGLBuffer>(m_boundArrayBuffer));
2432 case GraphicsContext3D::BLEND:
2433 return getBooleanParameter(pname);
2434 case GraphicsContext3D::BLEND_COLOR:
2435 return getWebGLFloatArrayParameter(pname);
2436 case GraphicsContext3D::BLEND_DST_ALPHA:
2437 return getUnsignedIntParameter(pname);
2438 case GraphicsContext3D::BLEND_DST_RGB:
2439 return getUnsignedIntParameter(pname);
2440 case GraphicsContext3D::BLEND_EQUATION_ALPHA:
2441 return getUnsignedIntParameter(pname);
2442 case GraphicsContext3D::BLEND_EQUATION_RGB:
2443 return getUnsignedIntParameter(pname);
2444 case GraphicsContext3D::BLEND_SRC_ALPHA:
2445 return getUnsignedIntParameter(pname);
2446 case GraphicsContext3D::BLEND_SRC_RGB:
2447 return getUnsignedIntParameter(pname);
2448 case GraphicsContext3D::BLUE_BITS:
2449 return getIntParameter(pname);
2450 case GraphicsContext3D::COLOR_CLEAR_VALUE:
2451 return getWebGLFloatArrayParameter(pname);
2452 case GraphicsContext3D::COLOR_WRITEMASK:
2453 return getBooleanArrayParameter(pname);
2454 case GraphicsContext3D::COMPRESSED_TEXTURE_FORMATS:
2455 return WebGLGetInfo(Uint32Array::create(m_compressedTextureFormats.data(), m_compressedTextureFormats.size()));
2456 case GraphicsContext3D::CULL_FACE:
2457 return getBooleanParameter(pname);
2458 case GraphicsContext3D::CULL_FACE_MODE:
2459 return getUnsignedIntParameter(pname);
2460 case GraphicsContext3D::CURRENT_PROGRAM:
2461 return WebGLGetInfo(PassRefPtr<WebGLProgram>(m_currentProgram));
2462 case GraphicsContext3D::DEPTH_BITS:
2463 if (!m_framebufferBinding && !m_attributes.depth)
2464 return WebGLGetInfo(intZero);
2465 return getIntParameter(pname);
2466 case GraphicsContext3D::DEPTH_CLEAR_VALUE:
2467 return getFloatParameter(pname);
2468 case GraphicsContext3D::DEPTH_FUNC:
2469 return getUnsignedIntParameter(pname);
2470 case GraphicsContext3D::DEPTH_RANGE:
2471 return getWebGLFloatArrayParameter(pname);
2472 case GraphicsContext3D::DEPTH_TEST:
2473 return getBooleanParameter(pname);
2474 case GraphicsContext3D::DEPTH_WRITEMASK:
2475 return getBooleanParameter(pname);
2476 case GraphicsContext3D::DITHER:
2477 return getBooleanParameter(pname);
2478 case GraphicsContext3D::ELEMENT_ARRAY_BUFFER_BINDING:
2479 return WebGLGetInfo(PassRefPtr<WebGLBuffer>(m_boundVertexArrayObject->getElementArrayBuffer()));
2480 case GraphicsContext3D::FRAMEBUFFER_BINDING:
2481 return WebGLGetInfo(PassRefPtr<WebGLFramebuffer>(m_framebufferBinding));
2482 case GraphicsContext3D::FRONT_FACE:
2483 return getUnsignedIntParameter(pname);
2484 case GraphicsContext3D::GENERATE_MIPMAP_HINT:
2485 return getUnsignedIntParameter(pname);
2486 case GraphicsContext3D::GREEN_BITS:
2487 return getIntParameter(pname);
2488 case GraphicsContext3D::LINE_WIDTH:
2489 return getFloatParameter(pname);
2490 case GraphicsContext3D::MAX_COMBINED_TEXTURE_IMAGE_UNITS:
2491 return getIntParameter(pname);
2492 case GraphicsContext3D::MAX_CUBE_MAP_TEXTURE_SIZE:
2493 return getIntParameter(pname);
2494 case GraphicsContext3D::MAX_FRAGMENT_UNIFORM_VECTORS:
2495 return getIntParameter(pname);
2496 case GraphicsContext3D::MAX_RENDERBUFFER_SIZE:
2497 return getIntParameter(pname);
2498 case GraphicsContext3D::MAX_TEXTURE_IMAGE_UNITS:
2499 return getIntParameter(pname);
2500 case GraphicsContext3D::MAX_TEXTURE_SIZE:
2501 return getIntParameter(pname);
2502 case GraphicsContext3D::MAX_VARYING_VECTORS:
2503 return getIntParameter(pname);
2504 case GraphicsContext3D::MAX_VERTEX_ATTRIBS:
2505 return getIntParameter(pname);
2506 case GraphicsContext3D::MAX_VERTEX_TEXTURE_IMAGE_UNITS:
2507 return getIntParameter(pname);
2508 case GraphicsContext3D::MAX_VERTEX_UNIFORM_VECTORS:
2509 return getIntParameter(pname);
2510 case GraphicsContext3D::MAX_VIEWPORT_DIMS:
2511 return getWebGLIntArrayParameter(pname);
2512 case GraphicsContext3D::NUM_SHADER_BINARY_FORMATS:
2513 // FIXME: should we always return 0 for this?
2514 return getIntParameter(pname);
2515 case GraphicsContext3D::PACK_ALIGNMENT:
2516 return getIntParameter(pname);
2517 case GraphicsContext3D::POLYGON_OFFSET_FACTOR:
2518 return getFloatParameter(pname);
2519 case GraphicsContext3D::POLYGON_OFFSET_FILL:
2520 return getBooleanParameter(pname);
2521 case GraphicsContext3D::POLYGON_OFFSET_UNITS:
2522 return getFloatParameter(pname);
2523 case GraphicsContext3D::RED_BITS:
2524 return getIntParameter(pname);
2525 case GraphicsContext3D::RENDERBUFFER_BINDING:
2526 return WebGLGetInfo(PassRefPtr<WebGLRenderbuffer>(m_renderbufferBinding));
2527 case GraphicsContext3D::RENDERER:
2528 return WebGLGetInfo(String("WebKit WebGL"));
2529 case GraphicsContext3D::SAMPLE_BUFFERS:
2530 return getIntParameter(pname);
2531 case GraphicsContext3D::SAMPLE_COVERAGE_INVERT:
2532 return getBooleanParameter(pname);
2533 case GraphicsContext3D::SAMPLE_COVERAGE_VALUE:
2534 return getFloatParameter(pname);
2535 case GraphicsContext3D::SAMPLES:
2536 return getIntParameter(pname);
2537 case GraphicsContext3D::SCISSOR_BOX:
2538 return getWebGLIntArrayParameter(pname);
2539 case GraphicsContext3D::SCISSOR_TEST:
2540 return getBooleanParameter(pname);
2541 case GraphicsContext3D::SHADING_LANGUAGE_VERSION:
2542 return WebGLGetInfo("WebGL GLSL ES 1.0 (" + m_context->getString(GraphicsContext3D::SHADING_LANGUAGE_VERSION) + ")");
2543 case GraphicsContext3D::STENCIL_BACK_FAIL:
2544 return getUnsignedIntParameter(pname);
2545 case GraphicsContext3D::STENCIL_BACK_FUNC:
2546 return getUnsignedIntParameter(pname);
2547 case GraphicsContext3D::STENCIL_BACK_PASS_DEPTH_FAIL:
2548 return getUnsignedIntParameter(pname);
2549 case GraphicsContext3D::STENCIL_BACK_PASS_DEPTH_PASS:
2550 return getUnsignedIntParameter(pname);
2551 case GraphicsContext3D::STENCIL_BACK_REF:
2552 return getIntParameter(pname);
2553 case GraphicsContext3D::STENCIL_BACK_VALUE_MASK:
2554 return getUnsignedIntParameter(pname);
2555 case GraphicsContext3D::STENCIL_BACK_WRITEMASK:
2556 return getUnsignedIntParameter(pname);
2557 case GraphicsContext3D::STENCIL_BITS:
2558 if (!m_framebufferBinding && !m_attributes.stencil)
2559 return WebGLGetInfo(intZero);
2560 return getIntParameter(pname);
2561 case GraphicsContext3D::STENCIL_CLEAR_VALUE:
2562 return getIntParameter(pname);
2563 case GraphicsContext3D::STENCIL_FAIL:
2564 return getUnsignedIntParameter(pname);
2565 case GraphicsContext3D::STENCIL_FUNC:
2566 return getUnsignedIntParameter(pname);
2567 case GraphicsContext3D::STENCIL_PASS_DEPTH_FAIL:
2568 return getUnsignedIntParameter(pname);
2569 case GraphicsContext3D::STENCIL_PASS_DEPTH_PASS:
2570 return getUnsignedIntParameter(pname);
2571 case GraphicsContext3D::STENCIL_REF:
2572 return getIntParameter(pname);
2573 case GraphicsContext3D::STENCIL_TEST:
2574 return getBooleanParameter(pname);
2575 case GraphicsContext3D::STENCIL_VALUE_MASK:
2576 return getUnsignedIntParameter(pname);
2577 case GraphicsContext3D::STENCIL_WRITEMASK:
2578 return getUnsignedIntParameter(pname);
2579 case GraphicsContext3D::SUBPIXEL_BITS:
2580 return getIntParameter(pname);
2581 case GraphicsContext3D::TEXTURE_BINDING_2D:
2582 return WebGLGetInfo(PassRefPtr<WebGLTexture>(m_textureUnits[m_activeTextureUnit].m_texture2DBinding));
2583 case GraphicsContext3D::TEXTURE_BINDING_CUBE_MAP:
2584 return WebGLGetInfo(PassRefPtr<WebGLTexture>(m_textureUnits[m_activeTextureUnit].m_textureCubeMapBinding));
2585 case GraphicsContext3D::UNPACK_ALIGNMENT:
2586 return getIntParameter(pname);
2587 case GraphicsContext3D::UNPACK_FLIP_Y_WEBGL:
2588 return WebGLGetInfo(m_unpackFlipY);
2589 case GraphicsContext3D::UNPACK_PREMULTIPLY_ALPHA_WEBGL:
2590 return WebGLGetInfo(m_unpackPremultiplyAlpha);
2591 case GraphicsContext3D::UNPACK_COLORSPACE_CONVERSION_WEBGL:
2592 return WebGLGetInfo(m_unpackColorspaceConversion);
2593 case GraphicsContext3D::VENDOR:
2594 return WebGLGetInfo(String("WebKit"));
2595 case GraphicsContext3D::VERSION:
2596 return WebGLGetInfo("WebGL 1.0 (" + m_context->getString(GraphicsContext3D::VERSION) + ")");
2597 case GraphicsContext3D::VIEWPORT:
2598 return getWebGLIntArrayParameter(pname);
2599 case Extensions3D::FRAGMENT_SHADER_DERIVATIVE_HINT_OES: // OES_standard_derivatives
2600 if (m_oesStandardDerivatives)
2601 return getUnsignedIntParameter(Extensions3D::FRAGMENT_SHADER_DERIVATIVE_HINT_OES);
2602 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getParameter", "invalid parameter name, OES_standard_derivatives not enabled");
2603 return WebGLGetInfo();
2604 case WebGLDebugRendererInfo::UNMASKED_RENDERER_WEBGL:
2605 if (m_webglDebugRendererInfo)
2606 return WebGLGetInfo(m_context->getString(GraphicsContext3D::RENDERER));
2607 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getParameter", "invalid parameter name, WEBGL_debug_renderer_info not enabled");
2608 return WebGLGetInfo();
2609 case WebGLDebugRendererInfo::UNMASKED_VENDOR_WEBGL:
2610 if (m_webglDebugRendererInfo)
2611 return WebGLGetInfo(m_context->getString(GraphicsContext3D::VENDOR));
2612 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getParameter", "invalid parameter name, WEBGL_debug_renderer_info not enabled");
2613 return WebGLGetInfo();
2614 case Extensions3D::VERTEX_ARRAY_BINDING_OES: // OES_vertex_array_object
2615 if (m_oesVertexArrayObject) {
2616 if (!m_boundVertexArrayObject->isDefaultObject())
2617 return WebGLGetInfo(PassRefPtr<WebGLVertexArrayObjectOES>(m_boundVertexArrayObject));
2618 return WebGLGetInfo();
2620 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getParameter", "invalid parameter name, OES_vertex_array_object not enabled");
2621 return WebGLGetInfo();
2622 case Extensions3D::MAX_TEXTURE_MAX_ANISOTROPY_EXT: // EXT_texture_filter_anisotropic
2623 if (m_extTextureFilterAnisotropic)
2624 return getUnsignedIntParameter(Extensions3D::MAX_TEXTURE_MAX_ANISOTROPY_EXT);
2625 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getParameter", "invalid parameter name, EXT_texture_filter_anisotropic not enabled");
2626 return WebGLGetInfo();
2628 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getParameter", "invalid parameter name");
2629 return WebGLGetInfo();
2633 WebGLGetInfo WebGLRenderingContext::getProgramParameter(WebGLProgram* program, GC3Denum pname, ExceptionCode& ec)
2636 if (isContextLost() || !validateWebGLObject("getProgramParameter", program))
2637 return WebGLGetInfo();
2639 WebGLStateRestorer(this, false);
2642 case GraphicsContext3D::DELETE_STATUS:
2643 return WebGLGetInfo(program->isDeleted());
2644 case GraphicsContext3D::VALIDATE_STATUS:
2645 m_context->getProgramiv(objectOrZero(program), pname, &value);
2646 return WebGLGetInfo(static_cast<bool>(value));
2647 case GraphicsContext3D::LINK_STATUS:
2648 return WebGLGetInfo(program->getLinkStatus());
2649 case GraphicsContext3D::ATTACHED_SHADERS:
2650 case GraphicsContext3D::ACTIVE_ATTRIBUTES:
2651 case GraphicsContext3D::ACTIVE_UNIFORMS:
2652 m_context->getProgramiv(objectOrZero(program), pname, &value);
2653 return WebGLGetInfo(value);
2655 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getProgramParameter", "invalid parameter name");
2656 return WebGLGetInfo();
2660 String WebGLRenderingContext::getProgramInfoLog(WebGLProgram* program, ExceptionCode& ec)
2663 if (isContextLost())
2665 if (!validateWebGLObject("getProgramInfoLog", program))
2667 WebGLStateRestorer(this, false);
2668 return ensureNotNull(m_context->getProgramInfoLog(objectOrZero(program)));
2671 WebGLGetInfo WebGLRenderingContext::getRenderbufferParameter(GC3Denum target, GC3Denum pname, ExceptionCode& ec)
2674 if (isContextLost())
2675 return WebGLGetInfo();
2676 if (target != GraphicsContext3D::RENDERBUFFER) {
2677 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getRenderbufferParameter", "invalid target");
2678 return WebGLGetInfo();
2680 if (!m_renderbufferBinding || !m_renderbufferBinding->object()) {
2681 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "getRenderbufferParameter", "no renderbuffer bound");
2682 return WebGLGetInfo();
2685 if (m_renderbufferBinding->getInternalFormat() == GraphicsContext3D::DEPTH_STENCIL
2686 && !m_renderbufferBinding->isValid()) {
2687 ASSERT(!isDepthStencilSupported());
2690 case GraphicsContext3D::RENDERBUFFER_WIDTH:
2691 value = m_renderbufferBinding->getWidth();
2693 case GraphicsContext3D::RENDERBUFFER_HEIGHT:
2694 value = m_renderbufferBinding->getHeight();
2696 case GraphicsContext3D::RENDERBUFFER_RED_SIZE:
2697 case GraphicsContext3D::RENDERBUFFER_GREEN_SIZE:
2698 case GraphicsContext3D::RENDERBUFFER_BLUE_SIZE:
2699 case GraphicsContext3D::RENDERBUFFER_ALPHA_SIZE:
2702 case GraphicsContext3D::RENDERBUFFER_DEPTH_SIZE:
2705 case GraphicsContext3D::RENDERBUFFER_STENCIL_SIZE:
2708 case GraphicsContext3D::RENDERBUFFER_INTERNAL_FORMAT:
2709 return WebGLGetInfo(m_renderbufferBinding->getInternalFormat());
2711 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getRenderbufferParameter", "invalid parameter name");
2712 return WebGLGetInfo();
2714 return WebGLGetInfo(value);
2717 WebGLStateRestorer(this, false);
2720 case GraphicsContext3D::RENDERBUFFER_WIDTH:
2721 case GraphicsContext3D::RENDERBUFFER_HEIGHT:
2722 case GraphicsContext3D::RENDERBUFFER_RED_SIZE:
2723 case GraphicsContext3D::RENDERBUFFER_GREEN_SIZE:
2724 case GraphicsContext3D::RENDERBUFFER_BLUE_SIZE:
2725 case GraphicsContext3D::RENDERBUFFER_ALPHA_SIZE:
2726 case GraphicsContext3D::RENDERBUFFER_DEPTH_SIZE:
2727 case GraphicsContext3D::RENDERBUFFER_STENCIL_SIZE:
2728 m_context->getRenderbufferParameteriv(target, pname, &value);
2729 return WebGLGetInfo(value);
2730 case GraphicsContext3D::RENDERBUFFER_INTERNAL_FORMAT:
2731 return WebGLGetInfo(m_renderbufferBinding->getInternalFormat());
2733 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getRenderbufferParameter", "invalid parameter name");
2734 return WebGLGetInfo();
2738 WebGLGetInfo WebGLRenderingContext::getShaderParameter(WebGLShader* shader, GC3Denum pname, ExceptionCode& ec)
2741 if (isContextLost() || !validateWebGLObject("getShaderParameter", shader))
2742 return WebGLGetInfo();
2743 WebGLStateRestorer(this, false);
2746 case GraphicsContext3D::DELETE_STATUS:
2747 return WebGLGetInfo(shader->isDeleted());
2748 case GraphicsContext3D::COMPILE_STATUS:
2749 m_context->getShaderiv(objectOrZero(shader), pname, &value);
2750 return WebGLGetInfo(static_cast<bool>(value));
2751 case GraphicsContext3D::SHADER_TYPE:
2752 m_context->getShaderiv(objectOrZero(shader), pname, &value);
2753 return WebGLGetInfo(static_cast<unsigned int>(value));
2755 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getShaderParameter", "invalid parameter name");
2756 return WebGLGetInfo();
2760 String WebGLRenderingContext::getShaderInfoLog(WebGLShader* shader, ExceptionCode& ec)
2763 if (isContextLost())
2765 if (!validateWebGLObject("getShaderInfoLog", shader))
2767 WebGLStateRestorer(this, false);
2768 return ensureNotNull(m_context->getShaderInfoLog(objectOrZero(shader)));
2771 PassRefPtr<WebGLShaderPrecisionFormat> WebGLRenderingContext::getShaderPrecisionFormat(GC3Denum shaderType, GC3Denum precisionType, ExceptionCode& ec)
2774 if (isContextLost())
2776 switch (shaderType) {
2777 case GraphicsContext3D::VERTEX_SHADER:
2778 case GraphicsContext3D::FRAGMENT_SHADER:
2781 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getShaderPrecisionFormat", "invalid shader type");
2784 switch (precisionType) {
2785 case GraphicsContext3D::LOW_FLOAT:
2786 case GraphicsContext3D::MEDIUM_FLOAT:
2787 case GraphicsContext3D::HIGH_FLOAT:
2788 case GraphicsContext3D::LOW_INT:
2789 case GraphicsContext3D::MEDIUM_INT:
2790 case GraphicsContext3D::HIGH_INT:
2793 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getShaderPrecisionFormat", "invalid precision type");
2797 GC3Dint range[2] = {0, 0};
2798 GC3Dint precision = 0;
2799 #if !ENABLE(TIZEN_DAILY_UPVERSIONING)
2800 // FIXME: getShaderPrecisionFormat() should be implemented.
2801 m_context->getShaderPrecisionFormat(shaderType, precisionType, range, &precision);
2803 return WebGLShaderPrecisionFormat::create(range[0], range[1], precision);
2806 String WebGLRenderingContext::getShaderSource(WebGLShader* shader, ExceptionCode& ec)
2809 if (isContextLost())
2811 if (!validateWebGLObject("getShaderSource", shader))
2813 return ensureNotNull(shader->getSource());
2816 Vector<String> WebGLRenderingContext::getSupportedExtensions()
2818 Vector<String> result;
2819 if (m_context->getExtensions()->supports("GL_OES_texture_float"))
2820 result.append("OES_texture_float");
2821 if (m_context->getExtensions()->supports("GL_OES_standard_derivatives"))
2822 result.append("OES_standard_derivatives");
2823 if (m_context->getExtensions()->supports("GL_EXT_texture_filter_anisotropic"))
2824 result.append("WEBKIT_EXT_texture_filter_anisotropic");
2825 if (m_context->getExtensions()->supports("GL_OES_vertex_array_object"))
2826 result.append("OES_vertex_array_object");
2827 result.append("WEBKIT_WEBGL_lose_context");
2828 if (WebGLCompressedTextureS3TC::supported(this))
2829 result.append("WEBKIT_WEBGL_compressed_texture_s3tc");
2830 if (WebGLDepthTexture::supported(graphicsContext3D()))
2831 result.append("WEBKIT_WEBGL_depth_texture");
2833 if (allowPrivilegedExtensions()) {
2834 if (m_context->getExtensions()->supports("GL_ANGLE_translated_shader_source"))
2835 result.append("WEBGL_debug_shaders");
2836 result.append("WEBGL_debug_renderer_info");
2842 WebGLGetInfo WebGLRenderingContext::getTexParameter(GC3Denum target, GC3Denum pname, ExceptionCode& ec)
2845 if (isContextLost())
2846 return WebGLGetInfo();
2847 WebGLTexture* tex = validateTextureBinding("getTexParameter", target, false);
2849 return WebGLGetInfo();
2850 WebGLStateRestorer(this, false);
2853 case GraphicsContext3D::TEXTURE_MAG_FILTER:
2854 case GraphicsContext3D::TEXTURE_MIN_FILTER:
2855 case GraphicsContext3D::TEXTURE_WRAP_S:
2856 case GraphicsContext3D::TEXTURE_WRAP_T:
2857 m_context->getTexParameteriv(target, pname, &value);
2858 return WebGLGetInfo(static_cast<unsigned int>(value));
2859 case Extensions3D::TEXTURE_MAX_ANISOTROPY_EXT: // EXT_texture_filter_anisotropic
2860 if (m_extTextureFilterAnisotropic) {
2861 m_context->getTexParameteriv(target, pname, &value);
2862 return WebGLGetInfo(static_cast<unsigned int>(value));
2864 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getTexParameter", "invalid parameter name, EXT_texture_filter_anisotropic not enabled");
2865 return WebGLGetInfo();
2867 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getTexParameter", "invalid parameter name");
2868 return WebGLGetInfo();
2872 WebGLGetInfo WebGLRenderingContext::getUniform(WebGLProgram* program, const WebGLUniformLocation* uniformLocation, ExceptionCode& ec)
2875 if (isContextLost() || !validateWebGLObject("getUniform", program))
2876 return WebGLGetInfo();
2877 if (!uniformLocation || uniformLocation->program() != program) {
2878 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "getUniform", "no uniformlocation or not valid for this program");
2879 return WebGLGetInfo();
2881 GC3Dint location = uniformLocation->location();
2883 WebGLStateRestorer(this, false);
2884 // FIXME: make this more efficient using WebGLUniformLocation and caching types in it
2885 GC3Dint activeUniforms = 0;
2886 m_context->getProgramiv(objectOrZero(program), GraphicsContext3D::ACTIVE_UNIFORMS, &activeUniforms);
2887 for (GC3Dint i = 0; i < activeUniforms; i++) {
2889 if (!m_context->getActiveUniform(objectOrZero(program), i, info))
2890 return WebGLGetInfo();
2891 // Strip "[0]" from the name if it's an array.
2892 if (info.size > 1 && info.name.endsWith("[0]"))
2893 info.name = info.name.left(info.name.length() - 3);
2894 // If it's an array, we need to iterate through each element, appending "[index]" to the name.
2895 for (GC3Dint index = 0; index < info.size; ++index) {
2896 String name = info.name;
2897 if (info.size > 1 && index >= 1) {
2899 name.append(String::number(index));
2902 // Now need to look this up by name again to find its location
2903 GC3Dint loc = m_context->getUniformLocation(objectOrZero(program), name);
2904 if (loc == location) {
2905 // Found it. Use the type in the ActiveInfo to determine the return type.
2907 unsigned int length;
2908 switch (info.type) {
2909 case GraphicsContext3D::BOOL:
2910 baseType = GraphicsContext3D::BOOL;
2913 case GraphicsContext3D::BOOL_VEC2:
2914 baseType = GraphicsContext3D::BOOL;
2917 case GraphicsContext3D::BOOL_VEC3:
2918 baseType = GraphicsContext3D::BOOL;
2921 case GraphicsContext3D::BOOL_VEC4:
2922 baseType = GraphicsContext3D::BOOL;
2925 case GraphicsContext3D::INT:
2926 baseType = GraphicsContext3D::INT;
2929 case GraphicsContext3D::INT_VEC2:
2930 baseType = GraphicsContext3D::INT;
2933 case GraphicsContext3D::INT_VEC3:
2934 baseType = GraphicsContext3D::INT;
2937 case GraphicsContext3D::INT_VEC4:
2938 baseType = GraphicsContext3D::INT;
2941 case GraphicsContext3D::FLOAT:
2942 baseType = GraphicsContext3D::FLOAT;
2945 case GraphicsContext3D::FLOAT_VEC2:
2946 baseType = GraphicsContext3D::FLOAT;
2949 case GraphicsContext3D::FLOAT_VEC3:
2950 baseType = GraphicsContext3D::FLOAT;
2953 case GraphicsContext3D::FLOAT_VEC4:
2954 baseType = GraphicsContext3D::FLOAT;
2957 case GraphicsContext3D::FLOAT_MAT2:
2958 baseType = GraphicsContext3D::FLOAT;
2961 case GraphicsContext3D::FLOAT_MAT3:
2962 baseType = GraphicsContext3D::FLOAT;
2965 case GraphicsContext3D::FLOAT_MAT4:
2966 baseType = GraphicsContext3D::FLOAT;
2969 case GraphicsContext3D::SAMPLER_2D:
2970 case GraphicsContext3D::SAMPLER_CUBE:
2971 baseType = GraphicsContext3D::INT;
2975 // Can't handle this type
2976 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "getUniform", "unhandled type");
2977 return WebGLGetInfo();
2980 case GraphicsContext3D::FLOAT: {
2981 GC3Dfloat value[16] = {0};
2982 m_context->getUniformfv(objectOrZero(program), location, value);
2984 return WebGLGetInfo(value[0]);
2985 return WebGLGetInfo(Float32Array::create(value, length));
2987 case GraphicsContext3D::INT: {
2988 GC3Dint value[4] = {0};
2989 m_context->getUniformiv(objectOrZero(program), location, value);
2991 return WebGLGetInfo(value[0]);
2992 return WebGLGetInfo(Int32Array::create(value, length));
2994 case GraphicsContext3D::BOOL: {
2995 GC3Dint value[4] = {0};
2996 m_context->getUniformiv(objectOrZero(program), location, value);
2998 bool boolValue[16] = {0};
2999 for (unsigned j = 0; j < length; j++)
3000 boolValue[j] = static_cast<bool>(value[j]);
3001 return WebGLGetInfo(boolValue, length);
3003 return WebGLGetInfo(static_cast<bool>(value[0]));
3011 // If we get here, something went wrong in our unfortunately complex logic above
3012 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "getUniform", "unknown error");
3013 return WebGLGetInfo();
3016 PassRefPtr<WebGLUniformLocation> WebGLRenderingContext::getUniformLocation(WebGLProgram* program, const String& name, ExceptionCode& ec)
3019 if (isContextLost() || !validateWebGLObject("getUniformLocation", program))
3021 if (!validateLocationLength("getUniformLocation", name))
3023 if (!validateString("getUniformLocation", name))
3025 if (isPrefixReserved(name))
3027 if (!program->getLinkStatus()) {
3028 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "getUniformLocation", "program not linked");
3031 WebGLStateRestorer(this, false);
3032 GC3Dint uniformLocation = m_context->getUniformLocation(objectOrZero(program), name);
3033 if (uniformLocation == -1)
3035 return WebGLUniformLocation::create(program, uniformLocation);
3038 WebGLGetInfo WebGLRenderingContext::getVertexAttrib(GC3Duint index, GC3Denum pname, ExceptionCode& ec)
3041 if (isContextLost())
3042 return WebGLGetInfo();
3043 WebGLStateRestorer(this, false);
3044 if (index >= m_maxVertexAttribs) {
3045 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "getVertexAttrib", "index out of range");
3046 return WebGLGetInfo();
3048 const WebGLVertexArrayObjectOES::VertexAttribState& state = m_boundVertexArrayObject->getVertexAttribState(index);
3050 case GraphicsContext3D::VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
3051 if ((!isGLES2Compliant() && !index && m_boundVertexArrayObject->getVertexAttribState(0).bufferBinding == m_vertexAttrib0Buffer)
3052 || !state.bufferBinding
3053 || !state.bufferBinding->object())
3054 return WebGLGetInfo();
3055 return WebGLGetInfo(PassRefPtr<WebGLBuffer>(state.bufferBinding));
3056 case GraphicsContext3D::VERTEX_ATTRIB_ARRAY_ENABLED:
3057 return WebGLGetInfo(state.enabled);
3058 case GraphicsContext3D::VERTEX_ATTRIB_ARRAY_NORMALIZED:
3059 return WebGLGetInfo(state.normalized);
3060 case GraphicsContext3D::VERTEX_ATTRIB_ARRAY_SIZE:
3061 return WebGLGetInfo(state.size);
3062 case GraphicsContext3D::VERTEX_ATTRIB_ARRAY_STRIDE:
3063 return WebGLGetInfo(state.originalStride);
3064 case GraphicsContext3D::VERTEX_ATTRIB_ARRAY_TYPE:
3065 return WebGLGetInfo(state.type);
3066 case GraphicsContext3D::CURRENT_VERTEX_ATTRIB:
3067 return WebGLGetInfo(Float32Array::create(m_vertexAttribValue[index].value, 4));
3069 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getVertexAttrib", "invalid parameter name");
3070 return WebGLGetInfo();
3074 long long WebGLRenderingContext::getVertexAttribOffset(GC3Duint index, GC3Denum pname)
3076 if (isContextLost())
3078 GC3Dsizeiptr result = m_context->getVertexAttribOffset(index, pname);
3079 cleanupAfterGraphicsCall(false);
3080 return static_cast<long long>(result);
3083 void WebGLRenderingContext::hint(GC3Denum target, GC3Denum mode)
3085 if (isContextLost())
3087 bool isValid = false;
3089 case GraphicsContext3D::GENERATE_MIPMAP_HINT:
3092 case Extensions3D::FRAGMENT_SHADER_DERIVATIVE_HINT_OES: // OES_standard_derivatives
3093 if (m_oesStandardDerivatives)
3098 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "hint", "invalid target");
3101 m_context->hint(target, mode);
3102 cleanupAfterGraphicsCall(false);
3105 GC3Dboolean WebGLRenderingContext::isBuffer(WebGLBuffer* buffer)
3107 if (!buffer || isContextLost())
3110 if (!buffer->hasEverBeenBound())
3113 return m_context->isBuffer(buffer->object());
3116 bool WebGLRenderingContext::isContextLost()
3118 return m_contextLost;
3121 GC3Dboolean WebGLRenderingContext::isEnabled(GC3Denum cap)
3123 if (isContextLost() || !validateCapability("isEnabled", cap))
3125 if (cap == GraphicsContext3D::STENCIL_TEST)
3126 return m_stencilEnabled;
3127 return m_context->isEnabled(cap);
3130 GC3Dboolean WebGLRenderingContext::isFramebuffer(WebGLFramebuffer* framebuffer)
3132 if (!framebuffer || isContextLost())
3135 if (!framebuffer->hasEverBeenBound())
3138 return m_context->isFramebuffer(framebuffer->object());
3141 GC3Dboolean WebGLRenderingContext::isProgram(WebGLProgram* program)
3143 if (!program || isContextLost())
3146 return m_context->isProgram(program->object());
3149 GC3Dboolean WebGLRenderingContext::isRenderbuffer(WebGLRenderbuffer* renderbuffer)
3151 if (!renderbuffer || isContextLost())
3154 if (!renderbuffer->hasEverBeenBound())
3157 return m_context->isRenderbuffer(renderbuffer->object());
3160 GC3Dboolean WebGLRenderingContext::isShader(WebGLShader* shader)
3162 if (!shader || isContextLost())
3165 return m_context->isShader(shader->object());
3168 GC3Dboolean WebGLRenderingContext::isTexture(WebGLTexture* texture)
3170 if (!texture || isContextLost())
3173 if (!texture->hasEverBeenBound())
3176 return m_context->isTexture(texture->object());
3179 void WebGLRenderingContext::lineWidth(GC3Dfloat width)
3181 if (isContextLost())
3183 m_context->lineWidth(width);
3184 cleanupAfterGraphicsCall(false);
3187 void WebGLRenderingContext::linkProgram(WebGLProgram* program, ExceptionCode& ec)
3190 if (isContextLost() || !validateWebGLObject("linkProgram", program))
3192 if (!isGLES2Compliant()) {
3193 if (!program->getAttachedShader(GraphicsContext3D::VERTEX_SHADER) || !program->getAttachedShader(GraphicsContext3D::FRAGMENT_SHADER)) {
3194 program->setLinkStatus(false);
3199 m_context->linkProgram(objectOrZero(program));
3200 program->increaseLinkCount();
3201 cleanupAfterGraphicsCall(false);
3204 void WebGLRenderingContext::pixelStorei(GC3Denum pname, GC3Dint param)
3206 if (isContextLost())
3209 case GraphicsContext3D::UNPACK_FLIP_Y_WEBGL:
3210 m_unpackFlipY = param;
3212 case GraphicsContext3D::UNPACK_PREMULTIPLY_ALPHA_WEBGL:
3213 m_unpackPremultiplyAlpha = param;
3215 case GraphicsContext3D::UNPACK_COLORSPACE_CONVERSION_WEBGL:
3216 if (param == GraphicsContext3D::BROWSER_DEFAULT_WEBGL || param == GraphicsContext3D::NONE)
3217 m_unpackColorspaceConversion = static_cast<GC3Denum>(param);
3219 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "pixelStorei", "invalid parameter for UNPACK_COLORSPACE_CONVERSION_WEBGL");
3223 case GraphicsContext3D::PACK_ALIGNMENT:
3224 case GraphicsContext3D::UNPACK_ALIGNMENT:
3225 if (param == 1 || param == 2 || param == 4 || param == 8) {
3226 if (pname == GraphicsContext3D::PACK_ALIGNMENT)
3227 m_packAlignment = param;
3228 else // GraphicsContext3D::UNPACK_ALIGNMENT:
3229 m_unpackAlignment = param;
3230 m_context->pixelStorei(pname, param);
3231 cleanupAfterGraphicsCall(false);
3233 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "pixelStorei", "invalid parameter for alignment");
3238 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "pixelStorei", "invalid parameter name");
3243 void WebGLRenderingContext::polygonOffset(GC3Dfloat factor, GC3Dfloat units)
3245 if (isContextLost())
3247 m_context->polygonOffset(factor, units);
3248 cleanupAfterGraphicsCall(false);
3251 void WebGLRenderingContext::readPixels(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height, GC3Denum format, GC3Denum type, ArrayBufferView* pixels, ExceptionCode&)
3253 if (isContextLost())
3255 // Due to WebGL's same-origin restrictions, it is not possible to
3256 // taint the origin using the WebGL API.
3257 ASSERT(canvas()->originClean());
3258 // Validate input parameters.
3260 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "readPixels", "no destination ArrayBufferView");
3264 case GraphicsContext3D::ALPHA:
3265 case GraphicsContext3D::RGB:
3266 case GraphicsContext3D::RGBA:
3269 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "readPixels", "invalid format");
3273 case GraphicsContext3D::UNSIGNED_BYTE:
3274 case GraphicsContext3D::UNSIGNED_SHORT_5_6_5:
3275 case GraphicsContext3D::UNSIGNED_SHORT_4_4_4_4:
3276 case GraphicsContext3D::UNSIGNED_SHORT_5_5_5_1:
3279 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "readPixels", "invalid type");
3282 if (format != GraphicsContext3D::RGBA || type != GraphicsContext3D::UNSIGNED_BYTE) {
3283 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "readPixels", "format not RGBA or type not UNSIGNED_BYTE");
3286 // Validate array type against pixel type.
3287 if (pixels->getType() != ArrayBufferView::TypeUint8) {
3288 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "readPixels", "ArrayBufferView not Uint8Array");
3291 const char* reason = "framebuffer incomplete";
3292 if (m_framebufferBinding && !m_framebufferBinding->onAccess(graphicsContext3D(), !isResourceSafe(), &reason)) {
3293 synthesizeGLError(GraphicsContext3D::INVALID_FRAMEBUFFER_OPERATION, "readPixels", reason);
3296 // Calculate array size, taking into consideration of PACK_ALIGNMENT.
3297 unsigned int totalBytesRequired;
3298 unsigned int padding;
3299 GC3Denum error = m_context->computeImageSizeInBytes(format, type, width, height, m_packAlignment, &totalBytesRequired, &padding);
3300 if (error != GraphicsContext3D::NO_ERROR) {
3301 synthesizeGLError(error, "readPixels", "invalid dimensions");
3304 if (pixels->byteLength() < totalBytesRequired) {
3305 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "readPixels", "ArrayBufferView not large enough for dimensions");
3308 clearIfComposited();
3309 void* data = pixels->baseAddress();
3312 ScopedDrawingBufferBinder binder(m_drawingBuffer.get(), m_framebufferBinding.get());
3313 m_context->readPixels(x, y, width, height, format, type, data);
3316 #if OS(DARWIN) || OS(QNX) || PLATFORM(EFL)
3317 // FIXME: remove this section when GL driver bug on Mac AND the GLES driver bug
3318 // on QC & Imagination QNX is fixed, i.e., when alpha is off, readPixels should
3319 // set alpha to 255 instead of 0.
3320 if (!m_framebufferBinding && !m_context->getContextAttributes().alpha) {
3321 unsigned char* pixels = reinterpret_cast<unsigned char*>(data);
3322 for (GC3Dsizei iy = 0; iy < height; ++iy) {
3323 for (GC3Dsizei ix = 0; ix < width; ++ix) {
3331 cleanupAfterGraphicsCall(false);
3334 void WebGLRenderingContext::releaseShaderCompiler()
3336 if (isContextLost())
3338 m_context->releaseShaderCompiler();
3339 cleanupAfterGraphicsCall(false);
3342 void WebGLRenderingContext::renderbufferStorage(GC3Denum target, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height)
3344 if (isContextLost())
3346 if (target != GraphicsContext3D::RENDERBUFFER) {
3347 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "renderbufferStorage", "invalid target");
3350 if (!m_renderbufferBinding || !m_renderbufferBinding->object()) {
3351 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "renderbufferStorage", "no bound renderbuffer");
3354 if (!validateSize("renderbufferStorage", width, height))
3356 switch (internalformat) {
3357 case GraphicsContext3D::DEPTH_COMPONENT16:
3358 case GraphicsContext3D::RGBA4:
3359 case GraphicsContext3D::RGB5_A1:
3360 case GraphicsContext3D::RGB565:
3361 case GraphicsContext3D::STENCIL_INDEX8:
3362 m_context->renderbufferStorage(target, internalformat, width, height);
3363 m_renderbufferBinding->setInternalFormat(internalformat);
3364 m_renderbufferBinding->setIsValid(true);
3365 m_renderbufferBinding->setSize(width, height);
3366 cleanupAfterGraphicsCall(false);
3368 case GraphicsContext3D::DEPTH_STENCIL:
3369 if (isDepthStencilSupported()) {
3370 m_context->renderbufferStorage(target, Extensions3D::DEPTH24_STENCIL8, width, height);
3371 cleanupAfterGraphicsCall(false);
3373 m_renderbufferBinding->setSize(width, height);
3374 m_renderbufferBinding->setIsValid(isDepthStencilSupported());
3375 m_renderbufferBinding->setInternalFormat(internalformat);
3378 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "renderbufferStorage", "invalid internalformat");
3384 void WebGLRenderingContext::sampleCoverage(GC3Dfloat value, GC3Dboolean invert)
3386 if (isContextLost())
3388 m_context->sampleCoverage(value, invert);
3389 cleanupAfterGraphicsCall(false);
3392 void WebGLRenderingContext::scissor(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height)
3394 if (isContextLost())
3396 if (!validateSize("scissor", width, height))
3398 m_context->scissor(x, y, width, height);
3399 cleanupAfterGraphicsCall(false);
3402 void WebGLRenderingContext::shaderSource(WebGLShader* shader, const String& string, ExceptionCode& ec)
3405 if (isContextLost() || !validateWebGLObject("shaderSource", shader))
3407 String stringWithoutComments = StripComments(string).result();
3408 if (!validateString("shaderSource", stringWithoutComments))
3410 shader->setSource(string);
3411 m_context->shaderSource(objectOrZero(shader), stringWithoutComments);
3412 cleanupAfterGraphicsCall(false);
3415 void WebGLRenderingContext::stencilFunc(GC3Denum func, GC3Dint ref, GC3Duint mask)
3417 if (isContextLost())
3419 if (!validateStencilFunc("stencilFunc", func))
3421 m_stencilFuncRef = ref;
3422 m_stencilFuncRefBack = ref;
3423 m_stencilFuncMask = mask;
3424 m_stencilFuncMaskBack = mask;
3425 m_context->stencilFunc(func, ref, mask);
3426 cleanupAfterGraphicsCall(false);
3429 void WebGLRenderingContext::stencilFuncSeparate(GC3Denum face, GC3Denum func, GC3Dint ref, GC3Duint mask)
3431 if (isContextLost())
3433 if (!validateStencilFunc("stencilFuncSeparate", func))
3436 case GraphicsContext3D::FRONT_AND_BACK:
3437 m_stencilFuncRef = ref;
3438 m_stencilFuncRefBack = ref;
3439 m_stencilFuncMask = mask;
3440 m_stencilFuncMaskBack = mask;
3442 case GraphicsContext3D::FRONT:
3443 m_stencilFuncRef = ref;
3444 m_stencilFuncMask = mask;
3446 case GraphicsContext3D::BACK:
3447 m_stencilFuncRefBack = ref;
3448 m_stencilFuncMaskBack = mask;
3451 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "stencilFuncSeparate", "invalid face");
3454 m_context->stencilFuncSeparate(face, func, ref, mask);
3455 cleanupAfterGraphicsCall(false);
3458 void WebGLRenderingContext::stencilMask(GC3Duint mask)
3460 if (isContextLost())
3462 m_stencilMask = mask;
3463 m_stencilMaskBack = mask;
3464 m_context->stencilMask(mask);
3465 cleanupAfterGraphicsCall(false);
3468 void WebGLRenderingContext::stencilMaskSeparate(GC3Denum face, GC3Duint mask)
3470 if (isContextLost())
3473 case GraphicsContext3D::FRONT_AND_BACK:
3474 m_stencilMask = mask;
3475 m_stencilMaskBack = mask;
3477 case GraphicsContext3D::FRONT:
3478 m_stencilMask = mask;
3480 case GraphicsContext3D::BACK:
3481 m_stencilMaskBack = mask;
3484 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "stencilMaskSeparate", "invalid face");
3487 m_context->stencilMaskSeparate(face, mask);
3488 cleanupAfterGraphicsCall(false);
3491 void WebGLRenderingContext::stencilOp(GC3Denum fail, GC3Denum zfail, GC3Denum zpass)
3493 if (isContextLost())
3495 m_context->stencilOp(fail, zfail, zpass);
3496 cleanupAfterGraphicsCall(false);
3499 void WebGLRenderingContext::stencilOpSeparate(GC3Denum face, GC3Denum fail, GC3Denum zfail, GC3Denum zpass)
3501 if (isContextLost())
3503 m_context->stencilOpSeparate(face, fail, zfail, zpass);
3504 cleanupAfterGraphicsCall(false);
3507 void WebGLRenderingContext::texImage2DBase(GC3Denum target, GC3Dint level, GC3Denum internalformat,
3508 GC3Dsizei width, GC3Dsizei height, GC3Dint border,
3509 GC3Denum format, GC3Denum type, void* pixels, ExceptionCode& ec)
3511 // FIXME: For now we ignore any errors returned
3513 if (!validateTexFuncParameters("texImage2D", NotTexSubImage2D, target, level, internalformat, width, height, border, format, type))
3515 WebGLTexture* tex = validateTextureBinding("texImage2D", target, true);
3518 if (!isGLES2NPOTStrict()) {
3519 if (level && WebGLTexture::isNPOT(width, height)) {
3520 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "texImage2D", "level > 0 not power of 2");
3525 // Note: Chromium's OpenGL implementation clears textures and isResourceSafe() is therefore true.
3526 // For other implementations, if they are using ANGLE_depth_texture, ANGLE depth textures
3527 // can not be cleared with texImage2D and must be cleared by binding to an fbo and calling
3529 if (isResourceSafe())
3530 m_context->texImage2D(target, level, internalformat, width, height, border, format, type, 0);
3532 bool succeed = m_context->texImage2DResourceSafe(target, level, internalformat, width, height,
3533 border, format, type, m_unpackAlignment);
3538 if (!validateSettableTexFormat("texImage2D", internalformat))
3540 m_context->texImage2D(target, level, internalformat, width, height,
3541 border, format, type, pixels);
3543 tex->setLevelInfo(target, level, internalformat, width, height, type);
3544 cleanupAfterGraphicsCall(false);
3547 void WebGLRenderingContext::texImage2DImpl(GC3Denum target, GC3Dint level, GC3Denum internalformat,
3548 GC3Denum format, GC3Denum type, Image* image,
3549 bool flipY, bool premultiplyAlpha, ExceptionCode& ec)
3552 if (!validateSettableTexFormat("texImage2D", internalformat))
3554 Vector<uint8_t> data;
3555 if (!m_context->extractImageData(image, format, type, flipY, premultiplyAlpha, m_unpackColorspaceConversion == GraphicsContext3D::NONE, data)) {
3556 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "texImage2D", "bad image data");
3559 if (m_unpackAlignment != 1)
3560 m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, 1);
3561 #if ENABLE(TIZEN_JPEG_IMAGE_SCALE_DECODING)
3562 unsigned int componentsPerPixel;
3563 unsigned int bytesPerComponent;
3564 if (!GraphicsContext3D::computeFormatAndTypeParameters(format, type, &componentsPerPixel, &bytesPerComponent)) {
3565 ASSERT_NOT_REACHED();
3568 int dataSize = data.size() / (componentsPerPixel * bytesPerComponent);
3569 int imageSize = image->width() * image->height();
3570 if (dataSize != imageSize) {
3571 double scale = sqrt(static_cast<double>(dataSize) / imageSize);
3572 texImage2DBase(target, level, internalformat, image->width()*scale, image->height()*scale, 0,
3573 format, type, data.data(), ec);
3576 texImage2DBase(target, level, internalformat, image->width(), image->height(), 0,
3577 format, type, data.data(), ec);
3578 if (m_unpackAlignment != 1)
3579 m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, m_unpackAlignment);
3582 void WebGLRenderingContext::texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat,
3583 GC3Dsizei width, GC3Dsizei height, GC3Dint border,
3584 GC3Denum format, GC3Denum type, ArrayBufferView* pixels, ExceptionCode& ec)
3586 if (isContextLost() || !validateTexFuncData("texImage2D", level, width, height, format, type, pixels, NullAllowed))
3588 void* data = pixels ? pixels->baseAddress() : 0;
3589 Vector<uint8_t> tempData;
3590 bool changeUnpackAlignment = false;
3591 if (data && (m_unpackFlipY || m_unpackPremultiplyAlpha)) {
3592 if (!m_context->extractTextureData(width, height, format, type,
3594 m_unpackFlipY, m_unpackPremultiplyAlpha,
3598 data = tempData.data();
3599 changeUnpackAlignment = true;
3601 if (changeUnpackAlignment)
3602 m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, 1);
3603 texImage2DBase(target, level, internalformat, width, height, border,
3604 format, type, data, ec);
3605 if (changeUnpackAlignment)
3606 m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, m_unpackAlignment);
3609 void WebGLRenderingContext::texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat,
3610 GC3Denum format, GC3Denum type, ImageData* pixels, ExceptionCode& ec)
3613 if (isContextLost())
3615 Vector<uint8_t> data;
3618 bool needConversion = true;
3619 // The data from ImageData is always of format RGBA8.
3620 // No conversion is needed if destination format is RGBA and type is USIGNED_BYTE and no Flip or Premultiply operation is required.
3621 if (!m_unpackFlipY && !m_unpackPremultiplyAlpha && format == GraphicsContext3D::RGBA && type == GraphicsContext3D::UNSIGNED_BYTE)
3622 needConversion = false;
3624 if (!m_context->extractImageData(pixels, format, type, m_unpackFlipY, m_unpackPremultiplyAlpha, data)) {
3625 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "texImage2D", "bad image data");
3629 if (m_unpackAlignment != 1)
3630 m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, 1);
3631 texImage2DBase(target, level, internalformat, pixels->width(), pixels->height(), 0, format, type, needConversion ? data.data() : pixels->data()->data(), ec);
3632 if (m_unpackAlignment != 1)
3633 m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, m_unpackAlignment);
3636 void WebGLRenderingContext::texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat,
3637 GC3Denum format, GC3Denum type, HTMLImageElement* image, ExceptionCode& ec)
3640 if (isContextLost())
3642 if (!validateHTMLImageElement("texImage2D", image))
3644 if (wouldTaintOrigin(image)) {
3649 texImage2DImpl(target, level, internalformat, format, type, image->cachedImage()->imageForRenderer(image->renderer()),
3650 m_unpackFlipY, m_unpackPremultiplyAlpha, ec);
3653 void WebGLRenderingContext::texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat,
3654 GC3Denum format, GC3Denum type, HTMLCanvasElement* canvas, ExceptionCode& ec)
3657 if (isContextLost())
3659 if (!canvas || !canvas->buffer()) {
3660 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "texImage2D", "no canvas");
3663 if (wouldTaintOrigin(canvas)) {
3668 WebGLTexture* texture = validateTextureBinding("texImage2D", target, true);
3669 // If possible, copy from the canvas element directly to the texture
3670 // via the GPU, without a read-back to system memory.
3671 if (GraphicsContext3D::TEXTURE_2D == target && texture && type == texture->getType(target, level)) {
3672 ImageBuffer* buffer = canvas->buffer();
3673 if (buffer && buffer->copyToPlatformTexture(*m_context.get(), texture->object(), internalformat, m_unpackPremultiplyAlpha, m_unpackFlipY)) {
3674 texture->setLevelInfo(target, level, internalformat, canvas->width(), canvas->height(), type);
3675 cleanupAfterGraphicsCall(false);
3680 RefPtr<ImageData> imageData = canvas->getImageData();
3682 texImage2D(target, level, internalformat, format, type, imageData.get(), ec);
3684 texImage2DImpl(target, level, internalformat, format, type, canvas->copiedImage(),
3685 m_unpackFlipY, m_unpackPremultiplyAlpha, ec);
3689 PassRefPtr<Image> WebGLRenderingContext::videoFrameToImage(HTMLVideoElement* video, ExceptionCode& ec)
3691 if (!video || !video->videoWidth() || !video->videoHeight()) {
3692 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "texImage2D", "no video");
3695 IntSize size(video->videoWidth(), video->videoHeight());
3696 ImageBuffer* buf = m_videoCache.imageBuffer(size);
3698 synthesizeGLError(GraphicsContext3D::OUT_OF_MEMORY, "texImage2D", "out of memory");
3701 if (wouldTaintOrigin(video)) {
3705 IntRect destRect(0, 0, size.width(), size.height());
3706 // FIXME: Turn this into a GPU-GPU texture copy instead of CPU readback.
3707 video->paintCurrentFrameInContext(buf->context(), destRect);
3708 return buf->copyImage(CopyBackingStore);
3711 void WebGLRenderingContext::texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat,
3712 GC3Denum format, GC3Denum type, HTMLVideoElement* video, ExceptionCode& ec)
3715 if (isContextLost())
3717 RefPtr<Image> image = videoFrameToImage(video, ec);
3720 texImage2DImpl(target, level, internalformat, format, type, image.get(), m_unpackFlipY, m_unpackPremultiplyAlpha, ec);
3724 void WebGLRenderingContext::texParameter(GC3Denum target, GC3Denum pname, GC3Dfloat paramf, GC3Dint parami, bool isFloat)
3726 if (isContextLost())
3728 WebGLTexture* tex = validateTextureBinding("texParameter", target, false);
3732 case GraphicsContext3D::TEXTURE_MIN_FILTER:
3733 case GraphicsContext3D::TEXTURE_MAG_FILTER:
3735 case GraphicsContext3D::TEXTURE_WRAP_S:
3736 case GraphicsContext3D::TEXTURE_WRAP_T:
3737 if ((isFloat && paramf != GraphicsContext3D::CLAMP_TO_EDGE && paramf != GraphicsContext3D::MIRRORED_REPEAT && paramf != GraphicsContext3D::REPEAT)
3738 || (!isFloat && parami != GraphicsContext3D::CLAMP_TO_EDGE && parami != GraphicsContext3D::MIRRORED_REPEAT && parami != GraphicsContext3D::REPEAT)) {
3739 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "texParameter", "invalid parameter");
3743 case Extensions3D::TEXTURE_MAX_ANISOTROPY_EXT: // EXT_texture_filter_anisotropic
3744 if (!m_extTextureFilterAnisotropic) {
3745 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "texParameter", "invalid parameter, EXT_texture_filter_anisotropic not enabled");
3750 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "texParameter", "invalid parameter name");
3754 tex->setParameterf(pname, paramf);
3755 m_context->texParameterf(target, pname, paramf);
3757 tex->setParameteri(pname, parami);
3758 m_context->texParameteri(target, pname, parami);
3760 cleanupAfterGraphicsCall(false);
3763 void WebGLRenderingContext::texParameterf(GC3Denum target, GC3Denum pname, GC3Dfloat param)
3765 texParameter(target, pname, param, 0, true);
3768 void WebGLRenderingContext::texParameteri(GC3Denum target, GC3Denum pname, GC3Dint param)
3770 texParameter(target, pname, 0, param, false);
3773 void WebGLRenderingContext::texSubImage2DBase(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
3774 GC3Dsizei width, GC3Dsizei height,
3775 GC3Denum format, GC3Denum type, void* pixels, ExceptionCode& ec)
3777 // FIXME: For now we ignore any errors returned
3779 if (isContextLost())
3781 if (!validateTexFuncParameters("texSubImage2D", TexSubImage2D, target, level, format, width, height, 0, format, type))
3783 if (!validateSize("texSubImage2D", xoffset, yoffset))
3785 if (!validateSettableTexFormat("texSubImage2D", format))
3787 WebGLTexture* tex = validateTextureBinding("texSubImage2D", target, true);
3790 if (xoffset + width > tex->getWidth(target, level) || yoffset + height > tex->getHeight(target, level)) {
3791 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "texSubImage2D", "dimensions out of range");
3794 if (tex->getInternalFormat(target, level) != format || tex->getType(target, level) != type) {
3795 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "texSubImage2D", "type and format do not match texture");
3798 m_context->texSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels);
3799 cleanupAfterGraphicsCall(false);
3802 void WebGLRenderingContext::texSubImage2DImpl(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
3803 GC3Denum format, GC3Denum type,
3804 Image* image, bool flipY, bool premultiplyAlpha, ExceptionCode& ec)
3807 if (isContextLost())
3809 Vector<uint8_t> data;
3810 if (!m_context->extractImageData(image, format, type, flipY, premultiplyAlpha, m_unpackColorspaceConversion == GraphicsContext3D::NONE, data)) {
3811 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "texSubImage2D", "bad image");
3814 if (m_unpackAlignment != 1)
3815 m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, 1);
3816 texSubImage2DBase(target, level, xoffset, yoffset, image->width(), image->height(),
3817 format, type, data.data(), ec);
3818 if (m_unpackAlignment != 1)
3819 m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, m_unpackAlignment);
3822 void WebGLRenderingContext::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
3823 GC3Dsizei width, GC3Dsizei height,
3824 GC3Denum format, GC3Denum type, ArrayBufferView* pixels, ExceptionCode& ec)
3826 if (isContextLost() || !validateTexFuncData("texSubImage2D", level, width, height, format, type, pixels, NullNotAllowed))
3828 void* data = pixels->baseAddress();
3829 Vector<uint8_t> tempData;
3830 bool changeUnpackAlignment = false;
3831 if (data && (m_unpackFlipY || m_unpackPremultiplyAlpha)) {
3832 if (!m_context->extractTextureData(width, height, format, type,
3834 m_unpackFlipY, m_unpackPremultiplyAlpha,
3838 data = tempData.data();
3839 changeUnpackAlignment = true;
3841 if (changeUnpackAlignment)
3842 m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, 1);
3843 texSubImage2DBase(target, level, xoffset, yoffset, width, height, format, type, data, ec);
3844 if (changeUnpackAlignment)
3845 m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, m_unpackAlignment);
3848 void WebGLRenderingContext::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
3849 GC3Denum format, GC3Denum type, ImageData* pixels, ExceptionCode& ec)
3852 if (isContextLost())
3856 Vector<uint8_t> data;
3857 bool needConversion = true;
3858 // The data from ImageData is always of format RGBA8.
3859 // No conversion is needed if destination format is RGBA and type is USIGNED_BYTE and no Flip or Premultiply operation is required.
3860 if (format == GraphicsContext3D::RGBA && type == GraphicsContext3D::UNSIGNED_BYTE && !m_unpackFlipY && !m_unpackPremultiplyAlpha)
3861 needConversion = false;
3863 if (!m_context->extractImageData(pixels, format, type, m_unpackFlipY, m_unpackPremultiplyAlpha, data)) {
3864 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "texSubImage2D", "bad image data");
3868 if (m_unpackAlignment != 1)
3869 m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, 1);
3870 texSubImage2DBase(target, level, xoffset, yoffset, pixels->width(), pixels->height(), format, type, needConversion ? data.data() : pixels->data()->data(), ec);
3871 if (m_unpackAlignment != 1)
3872 m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, m_unpackAlignment);
3875 void WebGLRenderingContext::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
3876 GC3Denum format, GC3Denum type, HTMLImageElement* image, ExceptionCode& ec)
3879 if (isContextLost())
3881 if (!validateHTMLImageElement("texSubImage2D", image))
3883 if (wouldTaintOrigin(image)) {
3887 texSubImage2DImpl(target, level, xoffset, yoffset, format, type, image->cachedImage()->imageForRenderer(image->renderer()),
3888 m_unpackFlipY, m_unpackPremultiplyAlpha, ec);
3891 void WebGLRenderingContext::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
3892 GC3Denum format, GC3Denum type, HTMLCanvasElement* canvas, ExceptionCode& ec)
3895 if (isContextLost())
3897 if (!canvas || !canvas->buffer()) {
3898 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "texSubImage2D", "no canvas");
3901 if (wouldTaintOrigin(canvas)) {
3905 RefPtr<ImageData> imageData = canvas->getImageData();
3907 texSubImage2D(target, level, xoffset, yoffset, format, type, imageData.get(), ec);
3909 texSubImage2DImpl(target, level, xoffset, yoffset, format, type, canvas->copiedImage(),
3910 m_unpackFlipY, m_unpackPremultiplyAlpha, ec);
3914 void WebGLRenderingContext::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
3915 GC3Denum format, GC3Denum type, HTMLVideoElement* video, ExceptionCode& ec)
3918 if (isContextLost())
3920 RefPtr<Image> image = videoFrameToImage(video, ec);
3923 texSubImage2DImpl(target, level, xoffset, yoffset, format, type, image.get(), m_unpackFlipY, m_unpackPremultiplyAlpha, ec);
3927 void WebGLRenderingContext::uniform1f(const WebGLUniformLocation* location, GC3Dfloat x, ExceptionCode& ec)
3930 if (isContextLost() || !location)
3933 if (location->program() != m_currentProgram) {
3934 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "uniform1f", "location not for current program");
3938 m_context->uniform1f(location->location(), x);
3939 cleanupAfterGraphicsCall(false);
3942 void WebGLRenderingContext::uniform1fv(const WebGLUniformLocation* location, Float32Array* v, ExceptionCode& ec)
3945 if (isContextLost() || !validateUniformParameters("uniform1fv", location, v, 1))
3948 m_context->uniform1fv(location->location(), v->length(), v->data());
3949 cleanupAfterGraphicsCall(false);
3952 void WebGLRenderingContext::uniform1fv(const WebGLUniformLocation* location, GC3Dfloat* v, GC3Dsizei size, ExceptionCode& ec)
3955 if (isContextLost() || !validateUniformParameters("uniform1fv", location, v, size, 1))
3958 m_context->uniform1fv(location->location(), size, v);
3959 cleanupAfterGraphicsCall(false);
3962 void WebGLRenderingContext::uniform1i(const WebGLUniformLocation* location, GC3Dint x, ExceptionCode& ec)
3965 if (isContextLost() || !location)
3968 if (location->program() != m_currentProgram) {
3969 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "uniform1i", "location not for current program");
3973 m_context->uniform1i(location->location(), x);
3974 cleanupAfterGraphicsCall(false);
3977 void WebGLRenderingContext::uniform1iv(const WebGLUniformLocation* location, Int32Array* v, ExceptionCode& ec)
3980 if (isContextLost() || !validateUniformParameters("uniform1iv", location, v, 1))
3983 m_context->uniform1iv(location->location(), v->length(), v->data());
3984 cleanupAfterGraphicsCall(false);
3987 void WebGLRenderingContext::uniform1iv(const WebGLUniformLocation* location, GC3Dint* v, GC3Dsizei size, ExceptionCode& ec)
3990 if (isContextLost() || !validateUniformParameters("uniform1iv", location, v, size, 1))
3993 m_context->uniform1iv(location->location(), size, v);
3994 cleanupAfterGraphicsCall(false);
3997 void WebGLRenderingContext::uniform2f(const WebGLUniformLocation* location, GC3Dfloat x, GC3Dfloat y, ExceptionCode& ec)
4000 if (isContextLost() || !location)
4003 if (location->program() != m_currentProgram) {
4004 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "uniform2f", "location not for current program");
4008 m_context->uniform2f(location->location(), x, y);
4009 cleanupAfterGraphicsCall(false);
4012 void WebGLRenderingContext::uniform2fv(const WebGLUniformLocation* location, Float32Array* v, ExceptionCode& ec)
4015 if (isContextLost() || !validateUniformParameters("uniform2fv", location, v, 2))
4018 m_context->uniform2fv(location->location(), v->length() / 2, v->data());
4019 cleanupAfterGraphicsCall(false);
4022 void WebGLRenderingContext::uniform2fv(const WebGLUniformLocation* location, GC3Dfloat* v, GC3Dsizei size, ExceptionCode& ec)
4025 if (isContextLost() || !validateUniformParameters("uniform2fv", location, v, size, 2))
4028 m_context->uniform2fv(location->location(), size / 2, v);
4029 cleanupAfterGraphicsCall(false);
4032 void WebGLRenderingContext::uniform2i(const WebGLUniformLocation* location, GC3Dint x, GC3Dint y, ExceptionCode& ec)
4035 if (isContextLost() || !location)
4038 if (location->program() != m_currentProgram) {
4039 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "uniform2i", "location not for current program");
4043 m_context->uniform2i(location->location(), x, y);
4044 cleanupAfterGraphicsCall(false);
4047 void WebGLRenderingContext::uniform2iv(const WebGLUniformLocation* location, Int32Array* v, ExceptionCode& ec)
4050 if (isContextLost() || !validateUniformParameters("uniform2iv", location, v, 2))
4053 m_context->uniform2iv(location->location(), v->length() / 2, v->data());
4054 cleanupAfterGraphicsCall(false);
4057 void WebGLRenderingContext::uniform2iv(const WebGLUniformLocation* location, GC3Dint* v, GC3Dsizei size, ExceptionCode& ec)
4060 if (isContextLost() || !validateUniformParameters("uniform2iv", location, v, size, 2))
4063 m_context->uniform2iv(location->location(), size / 2, v);
4064 cleanupAfterGraphicsCall(false);
4067 void WebGLRenderingContext::uniform3f(const WebGLUniformLocation* location, GC3Dfloat x, GC3Dfloat y, GC3Dfloat z, ExceptionCode& ec)
4070 if (isContextLost() || !location)
4073 if (location->program() != m_currentProgram) {
4074 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "uniform3f", "location not for current program");
4078 m_context->uniform3f(location->location(), x, y, z);
4079 cleanupAfterGraphicsCall(false);
4082 void WebGLRenderingContext::uniform3fv(const WebGLUniformLocation* location, Float32Array* v, ExceptionCode& ec)
4085 if (isContextLost() || !validateUniformParameters("uniform3fv", location, v, 3))
4088 m_context->uniform3fv(location->location(), v->length() / 3, v->data());
4089 cleanupAfterGraphicsCall(false);
4092 void WebGLRenderingContext::uniform3fv(const WebGLUniformLocation* location, GC3Dfloat* v, GC3Dsizei size, ExceptionCode& ec)
4095 if (isContextLost() || !validateUniformParameters("uniform3fv", location, v, size, 3))
4098 m_context->uniform3fv(location->location(), size / 3, v);
4099 cleanupAfterGraphicsCall(false);
4102 void WebGLRenderingContext::uniform3i(const WebGLUniformLocation* location, GC3Dint x, GC3Dint y, GC3Dint z, ExceptionCode& ec)
4105 if (isContextLost() || !location)
4108 if (location->program() != m_currentProgram) {
4109 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "uniform3i", "location not for current program");
4113 m_context->uniform3i(location->location(), x, y, z);
4114 cleanupAfterGraphicsCall(false);
4117 void WebGLRenderingContext::uniform3iv(const WebGLUniformLocation* location, Int32Array* v, ExceptionCode& ec)
4120 if (isContextLost() || !validateUniformParameters("uniform3iv", location, v, 3))
4123 m_context->uniform3iv(location->location(), v->length() / 3, v->data());
4124 cleanupAfterGraphicsCall(false);
4127 void WebGLRenderingContext::uniform3iv(const WebGLUniformLocation* location, GC3Dint* v, GC3Dsizei size, ExceptionCode& ec)
4130 if (isContextLost() || !validateUniformParameters("uniform3iv", location, v, size, 3))
4133 m_context->uniform3iv(location->location(), size / 3, v);
4134 cleanupAfterGraphicsCall(false);
4137 void WebGLRenderingContext::uniform4f(const WebGLUniformLocation* location, GC3Dfloat x, GC3Dfloat y, GC3Dfloat z, GC3Dfloat w, ExceptionCode& ec)
4140 if (isContextLost() || !location)
4143 if (location->program() != m_currentProgram) {
4144 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "uniform4f", "location not for current program");
4148 m_context->uniform4f(location->location(), x, y, z, w);
4149 cleanupAfterGraphicsCall(false);
4152 void WebGLRenderingContext::uniform4fv(const WebGLUniformLocation* location, Float32Array* v, ExceptionCode& ec)
4155 if (isContextLost() || !validateUniformParameters("uniform4fv", location, v, 4))
4158 m_context->uniform4fv(location->location(), v->length() / 4, v->data());
4159 cleanupAfterGraphicsCall(false);
4162 void WebGLRenderingContext::uniform4fv(const WebGLUniformLocation* location, GC3Dfloat* v, GC3Dsizei size, ExceptionCode& ec)
4165 if (isContextLost() || !validateUniformParameters("uniform4fv", location, v, size, 4))
4168 m_context->uniform4fv(location->location(), size / 4, v);
4169 cleanupAfterGraphicsCall(false);
4172 void WebGLRenderingContext::uniform4i(const WebGLUniformLocation* location, GC3Dint x, GC3Dint y, GC3Dint z, GC3Dint w, ExceptionCode& ec)
4175 if (isContextLost() || !location)
4178 if (location->program() != m_currentProgram) {
4179 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "uniform4i", "location not for current program");
4183 m_context->uniform4i(location->location(), x, y, z, w);
4184 cleanupAfterGraphicsCall(false);
4187 void WebGLRenderingContext::uniform4iv(const WebGLUniformLocation* location, Int32Array* v, ExceptionCode& ec)
4190 if (isContextLost() || !validateUniformParameters("uniform4iv", location, v, 4))
4193 m_context->uniform4iv(location->location(), v->length() / 4, v->data());
4194 cleanupAfterGraphicsCall(false);
4197 void WebGLRenderingContext::uniform4iv(const WebGLUniformLocation* location, GC3Dint* v, GC3Dsizei size, ExceptionCode& ec)
4200 if (isContextLost() || !validateUniformParameters("uniform4iv", location, v, size, 4))
4203 m_context->uniform4iv(location->location(), size / 4, v);
4204 cleanupAfterGraphicsCall(false);
4207 void WebGLRenderingContext::uniformMatrix2fv(const WebGLUniformLocation* location, GC3Dboolean transpose, Float32Array* v, ExceptionCode& ec)
4210 if (isContextLost() || !validateUniformMatrixParameters("uniformMatrix2fv", location, transpose, v, 4))
4212 m_context->uniformMatrix2fv(location->location(), v->length() / 4, transpose, v->data());
4213 cleanupAfterGraphicsCall(false);
4216 void WebGLRenderingContext::uniformMatrix2fv(const WebGLUniformLocation* location, GC3Dboolean transpose, GC3Dfloat* v, GC3Dsizei size, ExceptionCode& ec)
4219 if (isContextLost() || !validateUniformMatrixParameters("uniformMatrix2fv", location, transpose, v, size, 4))
4221 m_context->uniformMatrix2fv(location->location(), size / 4, transpose, v);
4222 cleanupAfterGraphicsCall(false);
4225 void WebGLRenderingContext::uniformMatrix3fv(const WebGLUniformLocation* location, GC3Dboolean transpose, Float32Array* v, ExceptionCode& ec)
4228 if (isContextLost() || !validateUniformMatrixParameters("uniformMatrix3fv", location, transpose, v, 9))
4230 m_context->uniformMatrix3fv(location->location(), v->length() / 9, transpose, v->data());
4231 cleanupAfterGraphicsCall(false);
4234 void WebGLRenderingContext::uniformMatrix3fv(const WebGLUniformLocation* location, GC3Dboolean transpose, GC3Dfloat* v, GC3Dsizei size, ExceptionCode& ec)
4237 if (isContextLost() || !validateUniformMatrixParameters("uniformMatrix3fv", location, transpose, v, size, 9))
4239 m_context->uniformMatrix3fv(location->location(), size / 9, transpose, v);
4240 cleanupAfterGraphicsCall(false);
4243 void WebGLRenderingContext::uniformMatrix4fv(const WebGLUniformLocation* location, GC3Dboolean transpose, Float32Array* v, ExceptionCode& ec)
4246 if (isContextLost() || !validateUniformMatrixParameters("uniformMatrix4fv", location, transpose, v, 16))
4248 m_context->uniformMatrix4fv(location->location(), v->length() / 16, transpose, v->data());
4249 cleanupAfterGraphicsCall(false);
4252 void WebGLRenderingContext::uniformMatrix4fv(const WebGLUniformLocation* location, GC3Dboolean transpose, GC3Dfloat* v, GC3Dsizei size, ExceptionCode& ec)
4255 if (isContextLost() || !validateUniformMatrixParameters("uniformMatrix4fv", location, transpose, v, size, 16))
4257 m_context->uniformMatrix4fv(location->location(), size / 16, transpose, v);
4258 cleanupAfterGraphicsCall(false);
4261 void WebGLRenderingContext::useProgram(WebGLProgram* program, ExceptionCode& ec)
4265 if (!checkObjectToBeBound("useProgram", program, deleted))
4269 if (program && !program->getLinkStatus()) {
4270 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "useProgram", "program not valid");
4271 cleanupAfterGraphicsCall(false);
4274 if (m_currentProgram != program) {
4275 if (m_currentProgram)
4276 m_currentProgram->onDetached(graphicsContext3D());
4277 m_currentProgram = program;
4278 m_context->useProgram(objectOrZero(program));
4280 program->onAttached();
4282 cleanupAfterGraphicsCall(false);
4285 void WebGLRenderingContext::validateProgram(WebGLProgram* program, ExceptionCode& ec)
4288 if (isContextLost() || !validateWebGLObject("validateProgram", program))
4290 m_context->validateProgram(objectOrZero(program));
4291 cleanupAfterGraphicsCall(false);
4294 void WebGLRenderingContext::vertexAttrib1f(GC3Duint index, GC3Dfloat v0)
4296 vertexAttribfImpl("vertexAttrib1f", index, 1, v0, 0.0f, 0.0f, 1.0f);
4299 void WebGLRenderingContext::vertexAttrib1fv(GC3Duint index, Float32Array* v)
4301 vertexAttribfvImpl("vertexAttrib1fv", index, v, 1);
4304 void WebGLRenderingContext::vertexAttrib1fv(GC3Duint index, GC3Dfloat* v, GC3Dsizei size)
4306 vertexAttribfvImpl("vertexAttrib1fv", index, v, size, 1);
4309 void WebGLRenderingContext::vertexAttrib2f(GC3Duint index, GC3Dfloat v0, GC3Dfloat v1)
4311 vertexAttribfImpl("vertexAttrib2f", index, 2, v0, v1, 0.0f, 1.0f);
4314 void WebGLRenderingContext::vertexAttrib2fv(GC3Duint index, Float32Array* v)
4316 vertexAttribfvImpl("vertexAttrib2fv", index, v, 2);
4319 void WebGLRenderingContext::vertexAttrib2fv(GC3Duint index, GC3Dfloat* v, GC3Dsizei size)
4321 vertexAttribfvImpl("vertexAttrib2fv", index, v, size, 2);
4324 void WebGLRenderingContext::vertexAttrib3f(GC3Duint index, GC3Dfloat v0, GC3Dfloat v1, GC3Dfloat v2)
4326 vertexAttribfImpl("vertexAttrib3f", index, 3, v0, v1, v2, 1.0f);
4329 void WebGLRenderingContext::vertexAttrib3fv(GC3Duint index, Float32Array* v)
4331 vertexAttribfvImpl("vertexAttrib3fv", index, v, 3);
4334 void WebGLRenderingContext::vertexAttrib3fv(GC3Duint index, GC3Dfloat* v, GC3Dsizei size)
4336 vertexAttribfvImpl("vertexAttrib3fv", index, v, size, 3);
4339 void WebGLRenderingContext::vertexAttrib4f(GC3Duint index, GC3Dfloat v0, GC3Dfloat v1, GC3Dfloat v2, GC3Dfloat v3)
4341 vertexAttribfImpl("vertexAttrib4f", index, 4, v0, v1, v2, v3);
4344 void WebGLRenderingContext::vertexAttrib4fv(GC3Duint index, Float32Array* v)
4346 vertexAttribfvImpl("vertexAttrib4fv", index, v, 4);
4349 void WebGLRenderingContext::vertexAttrib4fv(GC3Duint index, GC3Dfloat* v, GC3Dsizei size)
4351 vertexAttribfvImpl("vertexAttrib4fv", index, v, size, 4);
4354 void WebGLRenderingContext::vertexAttribPointer(GC3Duint index, GC3Dint size, GC3Denum type, GC3Dboolean normalized, GC3Dsizei stride, long long offset, ExceptionCode& ec)
4357 if (isContextLost())
4360 case GraphicsContext3D::BYTE:
4361 case GraphicsContext3D::UNSIGNED_BYTE:
4362 case GraphicsContext3D::SHORT:
4363 case GraphicsContext3D::UNSIGNED_SHORT:
4364 case GraphicsContext3D::FLOAT:
4367 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "vertexAttribPointer", "invalid type");
4370 if (index >= m_maxVertexAttribs) {
4371 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "vertexAttribPointer", "index out of range");
4374 if (size < 1 || size > 4 || stride < 0 || stride > 255 || offset < 0) {
4375 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "vertexAttribPointer", "bad size, stride or offset");
4378 if (!m_boundArrayBuffer) {
4379 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "vertexAttribPointer", "no bound ARRAY_BUFFER");
4382 // Determine the number of elements the bound buffer can hold, given the offset, size, type and stride
4383 unsigned int typeSize = sizeInBytes(type);
4385 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "vertexAttribPointer", "invalid type");
4388 if ((stride % typeSize) || (static_cast<GC3Dintptr>(offset) % typeSize)) {
4389 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "vertexAttribPointer", "stride or offset not valid for type");
4392 GC3Dsizei bytesPerElement = size * typeSize;
4394 GC3Dsizei validatedStride = stride ? stride : bytesPerElement;
4396 WebGLVertexArrayObjectOES::VertexAttribState& state = m_boundVertexArrayObject->getVertexAttribState(index);
4397 state.bufferBinding = m_boundArrayBuffer;
4398 state.bytesPerElement = bytesPerElement;
4401 state.normalized = normalized;
4402 state.stride = validatedStride;
4403 state.originalStride = stride;
4404 state.offset = static_cast<GC3Dintptr>(offset);
4405 m_context->vertexAttribPointer(index, size, type, normalized, stride, static_cast<GC3Dintptr>(offset));
4406 cleanupAfterGraphicsCall(false);
4409 void WebGLRenderingContext::viewport(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height)
4411 if (isContextLost())
4413 if (!validateSize("viewport", width, height))
4415 m_context->viewport(x, y, width, height);
4416 cleanupAfterGraphicsCall(false);
4419 void WebGLRenderingContext::forceLostContext(WebGLRenderingContext::LostContextMode mode)
4421 if (isContextLost()) {
4422 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "loseContext", "context already lost");
4426 m_contextGroup->loseContextGroup(mode);
4429 void WebGLRenderingContext::loseContextImpl(WebGLRenderingContext::LostContextMode mode)
4431 if (isContextLost())
4434 m_contextLost = true;
4435 m_contextLostMode = mode;
4437 detachAndRemoveAllObjects();
4439 if (m_drawingBuffer) {
4440 // Make absolutely sure we do not refer to an already-deleted texture or framebuffer.
4441 m_drawingBuffer->setTexture2DBinding(0);
4442 m_drawingBuffer->setFramebufferBinding(0);
4445 // There is no direct way to clear errors from a GL implementation and
4446 // looping until getError() becomes NO_ERROR might cause an infinite loop if
4447 // the driver or context implementation had a bug. So, loop a reasonably
4448 // large number of times to clear any existing errors.
4449 for (int i = 0; i < 100; ++i) {
4450 if (m_context->getError() == GraphicsContext3D::NO_ERROR)
4453 synthesizeGLError(GraphicsContext3D::CONTEXT_LOST_WEBGL, "loseContext", "context lost");
4455 // Don't allow restoration unless the context lost event has both been
4456 // dispatched and its default behavior prevented.
4457 m_restoreAllowed = false;
4459 // Always defer the dispatch of the context lost event, to implement
4460 // the spec behavior of queueing a task.
4461 m_dispatchContextLostEventTimer.startOneShot(0);
4464 void WebGLRenderingContext::forceRestoreContext()
4466 if (!isContextLost()) {
4467 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "restoreContext", "context not lost");
4471 if (!m_restoreAllowed) {
4472 if (m_contextLostMode == SyntheticLostContext)
4473 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "restoreContext", "context restoration not allowed");
4477 if (!m_restoreTimer.isActive())
4478 m_restoreTimer.startOneShot(0);
4481 #if USE(ACCELERATED_COMPOSITING)
4482 PlatformLayer* WebGLRenderingContext::platformLayer() const
4484 #if PLATFORM(CHROMIUM)
4485 if (m_drawingBuffer)
4486 return m_drawingBuffer->platformLayer();
4489 return m_context->platformLayer();
4493 void WebGLRenderingContext::removeSharedObject(WebGLSharedObject* object)
4495 m_contextGroup->removeObject(object);
4498 void WebGLRenderingContext::addSharedObject(WebGLSharedObject* object)
4500 ASSERT(!isContextLost());
4501 m_contextGroup->addObject(object);
4504 void WebGLRenderingContext::removeContextObject(WebGLContextObject* object)
4506 m_contextObjects.remove(object);
4509 void WebGLRenderingContext::addContextObject(WebGLContextObject* object)
4511 ASSERT(!isContextLost());
4512 m_contextObjects.add(object);
4515 void WebGLRenderingContext::detachAndRemoveAllObjects()
4517 while (m_contextObjects.size() > 0) {
4518 HashSet<WebGLContextObject*>::iterator it = m_contextObjects.begin();
4519 (*it)->detachContext();
4523 WebGLGetInfo WebGLRenderingContext::getBooleanParameter(GC3Denum pname)
4525 GC3Dboolean value = 0;
4526 m_context->getBooleanv(pname, &value);
4527 return WebGLGetInfo(static_cast<bool>(value));
4530 WebGLGetInfo WebGLRenderingContext::getBooleanArrayParameter(GC3Denum pname)
4532 if (pname != GraphicsContext3D::COLOR_WRITEMASK) {
4534 return WebGLGetInfo(0, 0);
4536 GC3Dboolean value[4] = {0};
4537 m_context->getBooleanv(pname, value);
4539 for (int ii = 0; ii < 4; ++ii)
4540 boolValue[ii] = static_cast<bool>(value[ii]);
4541 return WebGLGetInfo(boolValue, 4);
4544 WebGLGetInfo WebGLRenderingContext::getFloatParameter(GC3Denum pname)
4546 GC3Dfloat value = 0;
4547 m_context->getFloatv(pname, &value);
4548 return WebGLGetInfo(value);
4551 WebGLGetInfo WebGLRenderingContext::getIntParameter(GC3Denum pname)
4554 m_context->getIntegerv(pname, &value);
4555 return WebGLGetInfo(value);
4558 WebGLGetInfo WebGLRenderingContext::getUnsignedIntParameter(GC3Denum pname)
4561 m_context->getIntegerv(pname, &value);
4562 return WebGLGetInfo(static_cast<unsigned int>(value));
4565 WebGLGetInfo WebGLRenderingContext::getWebGLFloatArrayParameter(GC3Denum pname)
4567 GC3Dfloat value[4] = {0};
4568 m_context->getFloatv(pname, value);
4569 unsigned length = 0;
4571 case GraphicsContext3D::ALIASED_POINT_SIZE_RANGE:
4572 case GraphicsContext3D::ALIASED_LINE_WIDTH_RANGE:
4573 case GraphicsContext3D::DEPTH_RANGE:
4576 case GraphicsContext3D::BLEND_COLOR:
4577 case GraphicsContext3D::COLOR_CLEAR_VALUE:
4583 return WebGLGetInfo(Float32Array::create(value, length));
4586 WebGLGetInfo WebGLRenderingContext::getWebGLIntArrayParameter(GC3Denum pname)
4588 GC3Dint value[4] = {0};
4589 m_context->getIntegerv(pname, value);
4590 unsigned length = 0;
4592 case GraphicsContext3D::MAX_VIEWPORT_DIMS:
4595 case GraphicsContext3D::SCISSOR_BOX:
4596 case GraphicsContext3D::VIEWPORT:
4602 return WebGLGetInfo(Int32Array::create(value, length));
4605 void WebGLRenderingContext::handleNPOTTextures(bool prepareToDraw)
4607 bool resetActiveUnit = false;
4608 for (unsigned ii = 0; ii < m_textureUnits.size(); ++ii) {
4609 if ((m_textureUnits[ii].m_texture2DBinding && m_textureUnits[ii].m_texture2DBinding->needToUseBlackTexture())
4610 || (m_textureUnits[ii].m_textureCubeMapBinding && m_textureUnits[ii].m_textureCubeMapBinding->needToUseBlackTexture())) {
4611 if (ii != m_activeTextureUnit) {
4612 m_context->activeTexture(ii);
4613 resetActiveUnit = true;
4614 } else if (resetActiveUnit) {
4615 m_context->activeTexture(ii);
4616 resetActiveUnit = false;
4618 WebGLTexture* tex2D;
4619 WebGLTexture* texCubeMap;
4620 if (prepareToDraw) {
4621 tex2D = m_blackTexture2D.get();
4622 texCubeMap = m_blackTextureCubeMap.get();
4624 tex2D = m_textureUnits[ii].m_texture2DBinding.get();
4625 texCubeMap = m_textureUnits[ii].m_textureCubeMapBinding.get();
4627 if (m_textureUnits[ii].m_texture2DBinding && m_textureUnits[ii].m_texture2DBinding->needToUseBlackTexture())
4628 m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, objectOrZero(tex2D));
4629 if (m_textureUnits[ii].m_textureCubeMapBinding && m_textureUnits[ii].m_textureCubeMapBinding->needToUseBlackTexture())
4630 m_context->bindTexture(GraphicsContext3D::TEXTURE_CUBE_MAP, objectOrZero(texCubeMap));
4633 if (resetActiveUnit)
4634 m_context->activeTexture(m_activeTextureUnit);
4637 void WebGLRenderingContext::createFallbackBlackTextures1x1()
4639 unsigned char black[] = {0, 0, 0, 255};
4640 m_blackTexture2D = createTexture();
4641 m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_blackTexture2D->object());
4642 m_context->texImage2D(GraphicsContext3D::TEXTURE_2D, 0, GraphicsContext3D::RGBA, 1, 1,
4643 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, black);
4644 m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, 0);
4645 m_blackTextureCubeMap = createTexture();
4646 m_context->bindTexture(GraphicsContext3D::TEXTURE_CUBE_MAP, m_blackTextureCubeMap->object());
4647 m_context->texImage2D(GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_X, 0, GraphicsContext3D::RGBA, 1, 1,
4648 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, black);
4649 m_context->texImage2D(GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GraphicsContext3D::RGBA, 1, 1,
4650 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, black);
4651 m_context->texImage2D(GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GraphicsContext3D::RGBA, 1, 1,
4652 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, black);
4653 m_context->texImage2D(GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GraphicsContext3D::RGBA, 1, 1,
4654 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, black);
4655 m_context->texImage2D(GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GraphicsContext3D::RGBA, 1, 1,
4656 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, black);
4657 m_context->texImage2D(GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GraphicsContext3D::RGBA, 1, 1,
4658 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, black);
4659 m_context->bindTexture(GraphicsContext3D::TEXTURE_CUBE_MAP, 0);
4662 bool WebGLRenderingContext::isTexInternalFormatColorBufferCombinationValid(GC3Denum texInternalFormat,
4663 GC3Denum colorBufferFormat)
4665 unsigned need = GraphicsContext3D::getChannelBitsByFormat(texInternalFormat);
4666 unsigned have = GraphicsContext3D::getChannelBitsByFormat(colorBufferFormat);
4667 return (need & have) == need;
4670 GC3Denum WebGLRenderingContext::getBoundFramebufferColorFormat()
4672 if (m_framebufferBinding && m_framebufferBinding->object())
4673 return m_framebufferBinding->getColorBufferFormat();
4674 if (m_attributes.alpha)
4675 return GraphicsContext3D::RGBA;
4676 return GraphicsContext3D::RGB;
4679 int WebGLRenderingContext::getBoundFramebufferWidth()
4681 if (m_framebufferBinding && m_framebufferBinding->object())
4682 return m_framebufferBinding->getColorBufferWidth();
4683 return m_drawingBuffer ? m_drawingBuffer->size().width() : m_context->getInternalFramebufferSize().width();
4686 int WebGLRenderingContext::getBoundFramebufferHeight()
4688 if (m_framebufferBinding && m_framebufferBinding->object())
4689 return m_framebufferBinding->getColorBufferHeight();
4690 return m_drawingBuffer ? m_drawingBuffer->size().height() : m_context->getInternalFramebufferSize().height();
4693 WebGLTexture* WebGLRenderingContext::validateTextureBinding(const char* functionName, GC3Denum target, bool useSixEnumsForCubeMap)
4695 WebGLTexture* tex = 0;
4697 case GraphicsContext3D::TEXTURE_2D:
4698 tex = m_textureUnits[m_activeTextureUnit].m_texture2DBinding.get();
4700 case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_X:
4701 case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_X:
4702 case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Y:
4703 case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Y:
4704 case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Z:
4705 case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Z:
4706 if (!useSixEnumsForCubeMap) {
4707 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid texture target");
4710 tex = m_textureUnits[m_activeTextureUnit].m_textureCubeMapBinding.get();
4712 case GraphicsContext3D::TEXTURE_CUBE_MAP:
4713 if (useSixEnumsForCubeMap) {
4714 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid texture target");
4717 tex = m_textureUnits[m_activeTextureUnit].m_textureCubeMapBinding.get();
4720 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid texture target");
4724 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "no texture");
4728 bool WebGLRenderingContext::validateLocationLength(const char* functionName, const String& string)
4730 const unsigned maxWebGLLocationLength = 256;
4731 if (string.length() > maxWebGLLocationLength) {
4732 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "location length > 256");
4738 bool WebGLRenderingContext::validateSize(const char* functionName, GC3Dint x, GC3Dint y)
4740 if (x < 0 || y < 0) {
4741 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "size < 0");
4747 bool WebGLRenderingContext::validateString(const char* functionName, const String& string)
4749 for (size_t i = 0; i < string.length(); ++i) {
4750 if (!validateCharacter(string[i])) {
4751 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "string not ASCII");
4758 bool WebGLRenderingContext::validateTexFuncFormatAndType(const char* functionName, GC3Denum format, GC3Denum type, GC3Dint level)
4761 case GraphicsContext3D::ALPHA:
4762 case GraphicsContext3D::LUMINANCE:
4763 case GraphicsContext3D::LUMINANCE_ALPHA:
4764 case GraphicsContext3D::RGB:
4765 case GraphicsContext3D::RGBA:
4767 case GraphicsContext3D::DEPTH_STENCIL:
4768 case GraphicsContext3D::DEPTH_COMPONENT:
4769 if (m_webglDepthTexture)
4771 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "depth texture formats not enabled");
4774 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid texture format");
4779 case GraphicsContext3D::UNSIGNED_BYTE:
4780 case GraphicsContext3D::UNSIGNED_SHORT_5_6_5:
4781 case GraphicsContext3D::UNSIGNED_SHORT_4_4_4_4:
4782 case GraphicsContext3D::UNSIGNED_SHORT_5_5_5_1:
4784 case GraphicsContext3D::FLOAT:
4785 if (m_oesTextureFloat)
4787 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid texture type");
4789 case GraphicsContext3D::UNSIGNED_INT:
4790 case GraphicsContext3D::UNSIGNED_INT_24_8:
4791 case GraphicsContext3D::UNSIGNED_SHORT:
4792 if (m_webglDepthTexture)
4794 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid texture type");
4797 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid texture type");
4801 // Verify that the combination of format and type is supported.
4803 case GraphicsContext3D::ALPHA:
4804 case GraphicsContext3D::LUMINANCE:
4805 case GraphicsContext3D::LUMINANCE_ALPHA:
4806 if (type != GraphicsContext3D::UNSIGNED_BYTE
4807 && type != GraphicsContext3D::FLOAT) {
4808 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "invalid type for format");
4812 case GraphicsContext3D::RGB:
4813 if (type != GraphicsContext3D::UNSIGNED_BYTE
4814 && type != GraphicsContext3D::UNSIGNED_SHORT_5_6_5
4815 && type != GraphicsContext3D::FLOAT) {
4816 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "invalid type for RGB format");
4820 case GraphicsContext3D::RGBA:
4821 if (type != GraphicsContext3D::UNSIGNED_BYTE
4822 && type != GraphicsContext3D::UNSIGNED_SHORT_4_4_4_4
4823 && type != GraphicsContext3D::UNSIGNED_SHORT_5_5_5_1
4824 && type != GraphicsContext3D::FLOAT) {
4825 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "invalid type for RGBA format");
4829 case GraphicsContext3D::DEPTH_COMPONENT:
4830 if (!m_webglDepthTexture) {
4831 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid format. DEPTH_COMPONENT not enabled");
4834 if (type != GraphicsContext3D::UNSIGNED_SHORT
4835 && type != GraphicsContext3D::UNSIGNED_INT) {
4836 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "invalid type for DEPTH_COMPONENT format");
4840 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "level must be 0 for DEPTH_COMPONENT format");
4844 case GraphicsContext3D::DEPTH_STENCIL:
4845 if (!m_webglDepthTexture) {
4846 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid format. DEPTH_STENCIL not enabled");
4849 if (type != GraphicsContext3D::UNSIGNED_INT_24_8) {
4850 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "invalid type for DEPTH_STENCIL format");
4854 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "level must be 0 for DEPTH_STENCIL format");
4859 ASSERT_NOT_REACHED();
4865 bool WebGLRenderingContext::validateTexFuncLevel(const char* functionName, GC3Denum target, GC3Dint level)
4868 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "level < 0");
4872 case GraphicsContext3D::TEXTURE_2D:
4873 if (level > m_maxTextureLevel) {
4874 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "level out of range");
4878 case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_X:
4879 case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_X:
4880 case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Y:
4881 case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Y:
4882 case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Z:
4883 case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Z:
4884 if (level > m_maxCubeMapTextureLevel) {
4885 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "level out of range");
4890 // This function only checks if level is legal, so we return true and don't
4891 // generate INVALID_ENUM if target is illegal.
4895 bool WebGLRenderingContext::validateTexFuncParameters(const char* functionName,
4896 TexFuncValidationFunctionType functionType,
4897 GC3Denum target, GC3Dint level,
4898 GC3Denum internalformat,
4899 GC3Dsizei width, GC3Dsizei height, GC3Dint border,
4900 GC3Denum format, GC3Denum type)
4902 // We absolutely have to validate the format and type combination.
4903 // The texImage2D entry points taking HTMLImage, etc. will produce
4904 // temporary data based on this combination, so it must be legal.
4905 if (!validateTexFuncFormatAndType(functionName, format, type, level) || !validateTexFuncLevel(functionName, target, level))
4908 if (width < 0 || height < 0) {
4909 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "width or height < 0");
4914 case GraphicsContext3D::TEXTURE_2D:
4915 if (width > m_maxTextureSize || height > m_maxTextureSize) {
4916 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "width or height out of range");
4920 case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_X:
4921 case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_X:
4922 case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Y:
4923 case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Y:
4924 case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Z:
4925 case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Z:
4926 if (functionType != TexSubImage2D && width != height) {
4927 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "width != height for cube map");
4930 // No need to check height here. For texImage width == height.
4931 // For texSubImage that will be checked when checking yoffset + height is in range.
4932 if (width > m_maxCubeMapTextureSize) {
4933 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "width or height out of range for cube map");
4938 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid target");
4942 if (format != internalformat) {
4943 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "format != internalformat");
4948 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "border != 0");
4955 bool WebGLRenderingContext::validateTexFuncData(const char* functionName, GC3Dint level,
4956 GC3Dsizei width, GC3Dsizei height,
4957 GC3Denum format, GC3Denum type,
4958 ArrayBufferView* pixels,
4959 NullDisposition disposition)
4962 if (disposition == NullAllowed)
4964 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "no pixels");
4968 if (!validateTexFuncFormatAndType(functionName, format, type, level))
4970 if (!validateSettableTexFormat(functionName, format))
4974 case GraphicsContext3D::UNSIGNED_BYTE:
4975 if (pixels->getType() != ArrayBufferView::TypeUint8) {
4976 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "type UNSIGNED_BYTE but ArrayBufferView not Uint8Array");
4980 case GraphicsContext3D::UNSIGNED_SHORT_5_6_5:
4981 case GraphicsContext3D::UNSIGNED_SHORT_4_4_4_4:
4982 case GraphicsContext3D::UNSIGNED_SHORT_5_5_5_1:
4983 if (pixels->getType() != ArrayBufferView::TypeUint16) {
4984 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "type UNSIGNED_SHORT but ArrayBufferView not Uint16Array");
4988 case GraphicsContext3D::FLOAT: // OES_texture_float
4989 if (pixels->getType() != ArrayBufferView::TypeFloat32) {
4990 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "type FLOAT but ArrayBufferView not Float32Array");
4995 ASSERT_NOT_REACHED();
4998 unsigned int totalBytesRequired;
4999 GC3Denum error = m_context->computeImageSizeInBytes(format, type, width, height, m_unpackAlignment, &totalBytesRequired, 0);
5000 if (error != GraphicsContext3D::NO_ERROR) {
5001 synthesizeGLError(error, functionName, "invalid texture dimensions");
5004 if (pixels->byteLength() < totalBytesRequired) {
5005 if (m_unpackAlignment != 1) {
5006 error = m_context->computeImageSizeInBytes(format, type, width, height, 1, &totalBytesRequired, 0);
5007 if (pixels->byteLength() == totalBytesRequired) {
5008 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "ArrayBufferView not big enough for request with UNPACK_ALIGNMENT > 1");
5012 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "ArrayBufferView not big enough for request");
5018 bool WebGLRenderingContext::validateCompressedTexFormat(GC3Denum format)
5020 return m_compressedTextureFormats.contains(format);
5023 bool WebGLRenderingContext::validateCompressedTexFuncData(const char* functionName,
5024 GC3Dsizei width, GC3Dsizei height,
5025 GC3Denum format, ArrayBufferView* pixels)
5028 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "no pixels");
5031 if (width < 0 || height < 0) {
5032 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "width or height < 0");
5036 unsigned int bytesRequired = 0;
5039 case Extensions3D::COMPRESSED_RGB_S3TC_DXT1_EXT:
5040 case Extensions3D::COMPRESSED_RGBA_S3TC_DXT1_EXT:
5042 const int kBlockWidth = 4;
5043 const int kBlockHeight = 4;
5044 const int kBlockSize = 8;
5045 int numBlocksAcross = (width + kBlockWidth - 1) / kBlockWidth;
5046 int numBlocksDown = (height + kBlockHeight - 1) / kBlockHeight;
5047 int numBlocks = numBlocksAcross * numBlocksDown;
5048 bytesRequired = numBlocks * kBlockSize;
5051 case Extensions3D::COMPRESSED_RGBA_S3TC_DXT3_EXT:
5052 case Extensions3D::COMPRESSED_RGBA_S3TC_DXT5_EXT:
5054 const int kBlockWidth = 4;
5055 const int kBlockHeight = 4;
5056 const int kBlockSize = 16;
5057 int numBlocksAcross = (width + kBlockWidth - 1) / kBlockWidth;
5058 int numBlocksDown = (height + kBlockHeight - 1) / kBlockHeight;
5059 int numBlocks = numBlocksAcross * numBlocksDown;
5060 bytesRequired = numBlocks * kBlockSize;
5064 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid format");
5068 if (pixels->byteLength() != bytesRequired) {
5069 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "length of ArrayBufferView is not correct for dimensions");
5076 bool WebGLRenderingContext::validateCompressedTexDimensions(const char* functionName, GC3Dint level, GC3Dsizei width, GC3Dsizei height, GC3Denum format)
5079 case Extensions3D::COMPRESSED_RGB_S3TC_DXT1_EXT:
5080 case Extensions3D::COMPRESSED_RGBA_S3TC_DXT1_EXT:
5081 case Extensions3D::COMPRESSED_RGBA_S3TC_DXT3_EXT:
5082 case Extensions3D::COMPRESSED_RGBA_S3TC_DXT5_EXT: {
5083 const int kBlockWidth = 4;
5084 const int kBlockHeight = 4;
5085 bool widthValid = (level && width == 1) || (level && width == 2) || !(width % kBlockWidth);
5086 bool heightValid = (level && height == 1) || (level && height == 2) || !(height % kBlockHeight);
5087 if (!widthValid || !heightValid) {
5088 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "width or height invalid for level");
5098 bool WebGLRenderingContext::validateCompressedTexSubDimensions(const char* functionName, GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
5099 GC3Dsizei width, GC3Dsizei height, GC3Denum format, WebGLTexture* tex)
5101 if (xoffset < 0 || yoffset < 0) {
5102 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "xoffset or yoffset < 0");
5107 case Extensions3D::COMPRESSED_RGB_S3TC_DXT1_EXT:
5108 case Extensions3D::COMPRESSED_RGBA_S3TC_DXT1_EXT:
5109 case Extensions3D::COMPRESSED_RGBA_S3TC_DXT3_EXT:
5110 case Extensions3D::COMPRESSED_RGBA_S3TC_DXT5_EXT: {
5111 const int kBlockWidth = 4;
5112 const int kBlockHeight = 4;
5113 if ((xoffset % kBlockWidth) || (yoffset % kBlockHeight)) {
5114 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "xoffset or yoffset not multiple of 4");
5117 if (width - xoffset > tex->getWidth(target, level)
5118 || height - yoffset > tex->getHeight(target, level)) {
5119 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "dimensions out of range");
5122 return validateCompressedTexDimensions(functionName, level, width, height, format);
5129 bool WebGLRenderingContext::validateDrawMode(const char* functionName, GC3Denum mode)
5132 case GraphicsContext3D::POINTS:
5133 case GraphicsContext3D::LINE_STRIP:
5134 case GraphicsContext3D::LINE_LOOP:
5135 case GraphicsContext3D::LINES:
5136 case GraphicsContext3D::TRIANGLE_STRIP:
5137 case GraphicsContext3D::TRIANGLE_FAN:
5138 case GraphicsContext3D::TRIANGLES:
5141 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid draw mode");
5146 bool WebGLRenderingContext::validateStencilSettings(const char* functionName)
5148 if (m_stencilMask != m_stencilMaskBack || m_stencilFuncRef != m_stencilFuncRefBack || m_stencilFuncMask != m_stencilFuncMaskBack) {
5149 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "front and back stencils settings do not match");
5155 bool WebGLRenderingContext::validateStencilFunc(const char* functionName, GC3Denum func)
5158 case GraphicsContext3D::NEVER:
5159 case GraphicsContext3D::LESS:
5160 case GraphicsContext3D::LEQUAL:
5161 case GraphicsContext3D::GREATER:
5162 case GraphicsContext3D::GEQUAL:
5163 case GraphicsContext3D::EQUAL:
5164 case GraphicsContext3D::NOTEQUAL:
5165 case GraphicsContext3D::ALWAYS:
5168 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid function");
5173 void WebGLRenderingContext::printGLErrorToConsole(const String& message)
5175 if (!m_numGLErrorsToConsoleAllowed)
5178 --m_numGLErrorsToConsoleAllowed;
5179 printWarningToConsole(message);
5181 if (!m_numGLErrorsToConsoleAllowed)
5182 printWarningToConsole("WebGL: too many errors, no more errors will be reported to the console for this context.");
5185 void WebGLRenderingContext::printWarningToConsole(const String& message)
5189 Document* document = canvas()->document();
5192 Frame* frame = document->frame();
5195 DOMWindow* window = frame->domWindow();
5198 Console* console = window->console();
5201 console->addMessage(HTMLMessageSource, LogMessageType, WarningMessageLevel, message, document->url().string());
5204 bool WebGLRenderingContext::validateFramebufferFuncParameters(const char* functionName, GC3Denum target, GC3Denum attachment)
5206 if (target != GraphicsContext3D::FRAMEBUFFER) {
5207 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid target");
5210 switch (attachment) {
5211 case GraphicsContext3D::COLOR_ATTACHMENT0:
5212 case GraphicsContext3D::DEPTH_ATTACHMENT:
5213 case GraphicsContext3D::STENCIL_ATTACHMENT:
5214 case GraphicsContext3D::DEPTH_STENCIL_ATTACHMENT:
5217 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid attachment");
5223 bool WebGLRenderingContext::validateBlendEquation(const char* functionName, GC3Denum mode)
5226 case GraphicsContext3D::FUNC_ADD:
5227 case GraphicsContext3D::FUNC_SUBTRACT:
5228 case GraphicsContext3D::FUNC_REVERSE_SUBTRACT:
5231 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid mode");
5236 bool WebGLRenderingContext::validateBlendFuncFactors(const char* functionName, GC3Denum src, GC3Denum dst)
5238 if (((src == GraphicsContext3D::CONSTANT_COLOR || src == GraphicsContext3D::ONE_MINUS_CONSTANT_COLOR)
5239 && (dst == GraphicsContext3D::CONSTANT_ALPHA || dst == GraphicsContext3D::ONE_MINUS_CONSTANT_ALPHA))
5240 || ((dst == GraphicsContext3D::CONSTANT_COLOR || dst == GraphicsContext3D::ONE_MINUS_CONSTANT_COLOR)
5241 && (src == GraphicsContext3D::CONSTANT_ALPHA || src == GraphicsContext3D::ONE_MINUS_CONSTANT_ALPHA))) {
5242 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "incompatible src and dst");
5248 bool WebGLRenderingContext::validateCapability(const char* functionName, GC3Denum cap)
5251 case GraphicsContext3D::BLEND:
5252 case GraphicsContext3D::CULL_FACE:
5253 case GraphicsContext3D::DEPTH_TEST:
5254 case GraphicsContext3D::DITHER:
5255 case GraphicsContext3D::POLYGON_OFFSET_FILL:
5256 case GraphicsContext3D::SAMPLE_ALPHA_TO_COVERAGE:
5257 case GraphicsContext3D::SAMPLE_COVERAGE:
5258 case GraphicsContext3D::SCISSOR_TEST:
5259 case GraphicsContext3D::STENCIL_TEST:
5262 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid capability");
5267 bool WebGLRenderingContext::validateUniformParameters(const char* functionName, const WebGLUniformLocation* location, Float32Array* v, GC3Dsizei requiredMinSize)
5270 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "no array");
5273 return validateUniformMatrixParameters(functionName, location, false, v->data(), v->length(), requiredMinSize);
5276 bool WebGLRenderingContext::validateUniformParameters(const char* functionName, const WebGLUniformLocation* location, Int32Array* v, GC3Dsizei requiredMinSize)
5279 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "no array");
5282 return validateUniformMatrixParameters(functionName, location, false, v->data(), v->length(), requiredMinSize);
5285 bool WebGLRenderingContext::validateUniformParameters(const char* functionName, const WebGLUniformLocation* location, void* v, GC3Dsizei size, GC3Dsizei requiredMinSize)
5287 return validateUniformMatrixParameters(functionName, location, false, v, size, requiredMinSize);
5290 bool WebGLRenderingContext::validateUniformMatrixParameters(const char* functionName, const WebGLUniformLocation* location, GC3Dboolean transpose, Float32Array* v, GC3Dsizei requiredMinSize)
5293 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "no array");
5296 return validateUniformMatrixParameters(functionName, location, transpose, v->data(), v->length(), requiredMinSize);
5299 bool WebGLRenderingContext::validateUniformMatrixParameters(const char* functionName, const WebGLUniformLocation* location, GC3Dboolean transpose, void* v, GC3Dsizei size, GC3Dsizei requiredMinSize)
5303 if (location->program() != m_currentProgram) {
5304 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "location is not from current program");
5308 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "no array");
5312 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "transpose not FALSE");
5315 if (size < requiredMinSize || (size % requiredMinSize)) {
5316 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "invalid size");
5322 WebGLBuffer* WebGLRenderingContext::validateBufferDataParameters(const char* functionName, GC3Denum target, GC3Denum usage)
5324 WebGLBuffer* buffer = 0;
5326 case GraphicsContext3D::ELEMENT_ARRAY_BUFFER:
5327 buffer = m_boundVertexArrayObject->getElementArrayBuffer().get();
5329 case GraphicsContext3D::ARRAY_BUFFER:
5330 buffer = m_boundArrayBuffer.get();
5333 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid target");
5337 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "no buffer");
5341 case GraphicsContext3D::STREAM_DRAW:
5342 case GraphicsContext3D::STATIC_DRAW:
5343 case GraphicsContext3D::DYNAMIC_DRAW:
5346 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid usage");
5350 bool WebGLRenderingContext::validateHTMLImageElement(const char* functionName, HTMLImageElement* image)
5352 if (!image || !image->cachedImage()) {
5353 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "no image");
5356 const KURL& url = image->cachedImage()->response().url();
5357 if (url.isNull() || url.isEmpty() || !url.isValid()) {
5358 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "invalid image");
5364 void WebGLRenderingContext::vertexAttribfImpl(const char* functionName, GC3Duint index, GC3Dsizei expectedSize, GC3Dfloat v0, GC3Dfloat v1, GC3Dfloat v2, GC3Dfloat v3)
5366 if (isContextLost())
5368 if (index >= m_maxVertexAttribs) {
5369 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "index out of range");
5372 // In GL, we skip setting vertexAttrib0 values.
5373 if (index || isGLES2Compliant()) {
5374 switch (expectedSize) {
5376 m_context->vertexAttrib1f(index, v0);
5379 m_context->vertexAttrib2f(index, v0, v1);
5382 m_context->vertexAttrib3f(index, v0, v1, v2);
5385 m_context->vertexAttrib4f(index, v0, v1, v2, v3);
5388 cleanupAfterGraphicsCall(false);
5390 VertexAttribValue& attribValue = m_vertexAttribValue[index];
5391 attribValue.value[0] = v0;
5392 attribValue.value[1] = v1;
5393 attribValue.value[2] = v2;
5394 attribValue.value[3] = v3;
5397 void WebGLRenderingContext::vertexAttribfvImpl(const char* functionName, GC3Duint index, Float32Array* v, GC3Dsizei expectedSize)
5399 if (isContextLost())
5402 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "no array");
5405 vertexAttribfvImpl(functionName, index, v->data(), v->length(), expectedSize);
5408 void WebGLRenderingContext::vertexAttribfvImpl(const char* functionName, GC3Duint index, GC3Dfloat* v, GC3Dsizei size, GC3Dsizei expectedSize)
5410 if (isContextLost())
5413 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "no array");
5416 if (size < expectedSize) {
5417 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "invalid size");
5420 if (index >= m_maxVertexAttribs) {
5421 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "index out of range");
5424 // In GL, we skip setting vertexAttrib0 values.
5425 if (index || isGLES2Compliant()) {
5426 switch (expectedSize) {
5428 m_context->vertexAttrib1fv(index, v);
5431 m_context->vertexAttrib2fv(index, v);
5434 m_context->vertexAttrib3fv(index, v);
5437 m_context->vertexAttrib4fv(index, v);
5440 cleanupAfterGraphicsCall(false);
5442 VertexAttribValue& attribValue = m_vertexAttribValue[index];
5443 attribValue.initValue();
5444 for (int ii = 0; ii < expectedSize; ++ii)
5445 attribValue.value[ii] = v[ii];
5448 void WebGLRenderingContext::initVertexAttrib0()
5450 WebGLVertexArrayObjectOES::VertexAttribState& state = m_boundVertexArrayObject->getVertexAttribState(0);
5452 m_vertexAttrib0Buffer = createBuffer();
5453 m_context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, m_vertexAttrib0Buffer->object());
5454 m_context->bufferData(GraphicsContext3D::ARRAY_BUFFER, 0, GraphicsContext3D::DYNAMIC_DRAW);
5455 m_context->vertexAttribPointer(0, 4, GraphicsContext3D::FLOAT, false, 0, 0);
5456 state.bufferBinding = m_vertexAttrib0Buffer;
5457 m_context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, 0);
5458 m_context->enableVertexAttribArray(0);
5459 m_vertexAttrib0BufferSize = 0;
5460 m_vertexAttrib0BufferValue[0] = 0.0f;
5461 m_vertexAttrib0BufferValue[1] = 0.0f;
5462 m_vertexAttrib0BufferValue[2] = 0.0f;
5463 m_vertexAttrib0BufferValue[3] = 1.0f;
5464 m_forceAttrib0BufferRefill = false;
5465 m_vertexAttrib0UsedBefore = false;
5468 bool WebGLRenderingContext::simulateVertexAttrib0(GC3Dsizei numVertex)
5470 const WebGLVertexArrayObjectOES::VertexAttribState& state = m_boundVertexArrayObject->getVertexAttribState(0);
5471 const VertexAttribValue& attribValue = m_vertexAttribValue[0];
5472 if (!m_currentProgram)
5474 bool usingVertexAttrib0 = m_currentProgram->isUsingVertexAttrib0();
5475 if (usingVertexAttrib0)
5476 m_vertexAttrib0UsedBefore = true;
5477 if (state.enabled && usingVertexAttrib0)
5479 if (!usingVertexAttrib0 && !m_vertexAttrib0UsedBefore)
5481 m_vertexAttrib0UsedBefore = true;
5482 m_context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, m_vertexAttrib0Buffer->object());
5483 GC3Dsizeiptr bufferDataSize = (numVertex + 1) * 4 * sizeof(GC3Dfloat);
5484 if (bufferDataSize > m_vertexAttrib0BufferSize) {
5485 m_context->bufferData(GraphicsContext3D::ARRAY_BUFFER, bufferDataSize, 0, GraphicsContext3D::DYNAMIC_DRAW);
5486 m_vertexAttrib0BufferSize = bufferDataSize;
5487 m_forceAttrib0BufferRefill = true;
5489 if (usingVertexAttrib0
5490 && (m_forceAttrib0BufferRefill
5491 || attribValue.value[0] != m_vertexAttrib0BufferValue[0]
5492 || attribValue.value[1] != m_vertexAttrib0BufferValue[1]
5493 || attribValue.value[2] != m_vertexAttrib0BufferValue[2]
5494 || attribValue.value[3] != m_vertexAttrib0BufferValue[3])) {
5495 OwnArrayPtr<GC3Dfloat> bufferData = adoptArrayPtr(new GC3Dfloat[(numVertex + 1) * 4]);
5496 for (GC3Dsizei ii = 0; ii < numVertex + 1; ++ii) {
5497 bufferData[ii * 4] = attribValue.value[0];
5498 bufferData[ii * 4 + 1] = attribValue.value[1];
5499 bufferData[ii * 4 + 2] = attribValue.value[2];
5500 bufferData[ii * 4 + 3] = attribValue.value[3];
5502 m_vertexAttrib0BufferValue[0] = attribValue.value[0];
5503 m_vertexAttrib0BufferValue[1] = attribValue.value[1];
5504 m_vertexAttrib0BufferValue[2] = attribValue.value[2];
5505 m_vertexAttrib0BufferValue[3] = attribValue.value[3];
5506 m_forceAttrib0BufferRefill = false;
5507 m_context->bufferSubData(GraphicsContext3D::ARRAY_BUFFER, 0, bufferDataSize, bufferData.get());
5509 m_context->vertexAttribPointer(0, 4, GraphicsContext3D::FLOAT, 0, 0, 0);
5513 void WebGLRenderingContext::restoreStatesAfterVertexAttrib0Simulation()
5515 const WebGLVertexArrayObjectOES::VertexAttribState& state = m_boundVertexArrayObject->getVertexAttribState(0);
5516 if (state.bufferBinding != m_vertexAttrib0Buffer) {
5517 m_context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, objectOrZero(state.bufferBinding.get()));
5518 m_context->vertexAttribPointer(0, state.size, state.type, state.normalized, state.originalStride, state.offset);
5520 m_context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, objectOrZero(m_boundArrayBuffer.get()));
5523 void WebGLRenderingContext::dispatchContextLostEvent(Timer<WebGLRenderingContext>*)
5525 RefPtr<WebGLContextEvent> event = WebGLContextEvent::create(eventNames().webglcontextlostEvent, false, true, "");
5526 canvas()->dispatchEvent(event);
5527 m_restoreAllowed = event->defaultPrevented();
5528 if (m_contextLostMode == RealLostContext && m_restoreAllowed)
5529 m_restoreTimer.startOneShot(0);
5532 void WebGLRenderingContext::maybeRestoreContext(Timer<WebGLRenderingContext>*)
5534 ASSERT(m_contextLost);
5538 // The rendering context is not restored unless the default behavior of the
5539 // webglcontextlost event was prevented earlier.
5541 // Because of the way m_restoreTimer is set up for real vs. synthetic lost
5542 // context events, we don't have to worry about this test short-circuiting
5543 // the retry loop for real context lost events.
5544 if (!m_restoreAllowed)
5547 int contextLostReason = m_context->getExtensions()->getGraphicsResetStatusARB();
5549 switch (contextLostReason) {
5550 case GraphicsContext3D::NO_ERROR:
5551 // The GraphicsContext3D implementation might not fully
5552 // support GL_ARB_robustness semantics yet. Alternatively, the
5553 // WEBGL_lose_context extension might have been used to force
5556 case Extensions3D::GUILTY_CONTEXT_RESET_ARB:
5557 // The rendering context is not restored if this context was
5558 // guilty of causing the graphics reset.
5559 printWarningToConsole("WARNING: WebGL content on the page caused the graphics card to reset; not restoring the context");
5561 case Extensions3D::INNOCENT_CONTEXT_RESET_ARB:
5562 // Always allow the context to be restored.
5564 case Extensions3D::UNKNOWN_CONTEXT_RESET_ARB:
5565 // Warn. Ideally, prompt the user telling them that WebGL
5566 // content on the page might have caused the graphics card to
5567 // reset and ask them whether they want to continue running
5568 // the content. Only if they say "yes" should we start
5569 // attempting to restore the context.
5570 printWarningToConsole("WARNING: WebGL content on the page might have caused the graphics card to reset");
5574 RefPtr<GraphicsContext3D> context(GraphicsContext3D::create(m_attributes, canvas()->document()->view()->root()->hostWindow()));
5576 if (m_contextLostMode == RealLostContext)
5577 m_restoreTimer.startOneShot(secondsBetweenRestoreAttempts);
5579 // This likely shouldn't happen but is the best way to report it to the WebGL app.
5580 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "", "error restoring context");
5584 // Construct a new drawing buffer with the new GraphicsContext3D.
5585 if (m_drawingBuffer) {
5586 m_drawingBuffer->discardResources();
5587 DrawingBuffer::PreserveDrawingBuffer preserve = m_attributes.preserveDrawingBuffer ? DrawingBuffer::Preserve : DrawingBuffer::Discard;
5588 DrawingBuffer::AlphaRequirement alpha = m_attributes.alpha ? DrawingBuffer::Alpha : DrawingBuffer::Opaque;
5589 m_drawingBuffer = DrawingBuffer::create(context.get(), m_drawingBuffer->size(), preserve, alpha);
5590 m_drawingBuffer->bind();
5593 m_context = context;
5594 m_contextLost = false;
5595 initializeNewContext();
5596 canvas()->dispatchEvent(WebGLContextEvent::create(eventNames().webglcontextrestoredEvent, false, true, ""));
5599 String WebGLRenderingContext::ensureNotNull(const String& text) const
5602 return WTF::emptyString();
5606 WebGLRenderingContext::LRUImageBufferCache::LRUImageBufferCache(int capacity)
5607 : m_buffers(adoptArrayPtr(new OwnPtr<ImageBuffer>[capacity]))
5608 , m_capacity(capacity)
5612 ImageBuffer* WebGLRenderingContext::LRUImageBufferCache::imageBuffer(const IntSize& size)
5615 for (i = 0; i < m_capacity; ++i) {
5616 ImageBuffer* buf = m_buffers[i].get();
5619 if (buf->logicalSize() != size)
5625 OwnPtr<ImageBuffer> temp = ImageBuffer::create(size, 1);
5628 i = std::min(m_capacity - 1, i);
5629 m_buffers[i] = temp.release();
5631 ImageBuffer* buf = m_buffers[i].get();
5636 void WebGLRenderingContext::LRUImageBufferCache::bubbleToFront(int idx)
5638 for (int i = idx; i > 0; --i)
5639 m_buffers[i].swap(m_buffers[i-1]);
5644 String GetErrorString(GC3Denum error)
5647 case GraphicsContext3D::INVALID_ENUM:
5648 return "INVALID_ENUM";
5649 case GraphicsContext3D::INVALID_VALUE:
5650 return "INVALID_VALUE";
5651 case GraphicsContext3D::INVALID_OPERATION:
5652 return "INVALID_OPERATION";
5653 case GraphicsContext3D::OUT_OF_MEMORY:
5654 return "OUT_OF_MEMORY";
5655 case GraphicsContext3D::INVALID_FRAMEBUFFER_OPERATION:
5656 return "INVALID_FRAMEBUFFER_OPERATION";
5657 case GraphicsContext3D::CONTEXT_LOST_WEBGL:
5658 return "CONTEXT_LOST_WEBGL";
5660 return String::format("WebGL ERROR(%04x)", error);
5664 } // namespace anonymous
5666 void WebGLRenderingContext::synthesizeGLError(GC3Denum error, const char* functionName, const char* description)
5668 if (m_synthesizedErrorsToConsole) {
5669 String str = String("WebGL: ") + GetErrorString(error) + ": " + String(functionName) + ": " + String(description);
5670 printGLErrorToConsole(str);
5672 m_context->synthesizeGLError(error);
5676 void WebGLRenderingContext::printGLWarningToConsole(const char* functionName, const char* description)
5678 if (m_synthesizedErrorsToConsole) {
5679 String str = String("WebGL: ") + String(functionName) + ": " + String(description);
5680 printGLErrorToConsole(str);
5684 void WebGLRenderingContext::applyStencilTest()
5686 bool haveStencilBuffer = false;
5688 if (m_framebufferBinding)
5689 haveStencilBuffer = m_framebufferBinding->hasStencilBuffer();
5691 RefPtr<WebGLContextAttributes> attributes = getContextAttributes();
5692 haveStencilBuffer = attributes->stencil();
5694 enableOrDisable(GraphicsContext3D::STENCIL_TEST,
5695 m_stencilEnabled && haveStencilBuffer);
5698 void WebGLRenderingContext::enableOrDisable(GC3Denum capability, bool enable)
5701 m_context->enable(capability);
5703 m_context->disable(capability);
5706 IntSize WebGLRenderingContext::clampedCanvasSize()
5708 return IntSize(clamp(canvas()->width(), 1, m_maxViewportDims[0]),
5709 clamp(canvas()->height(), 1, m_maxViewportDims[1]));
5712 } // namespace WebCore
5714 #endif // ENABLE(WEBGL)