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());
529 m_context->setContextLostCallback(adoptPtr(new WebGLRenderingContextLostCallback(this)));
530 m_context->setErrorMessageCallback(adoptPtr(new WebGLRenderingContextErrorMessageCallback(this)));
533 void WebGLRenderingContext::setupFlags()
537 Page* p = canvas()->document()->page();
538 if (p && p->settings()->webGLErrorsToConsoleEnabled())
539 m_synthesizedErrorsToConsole = true;
541 m_isGLES2Compliant = m_context->isGLES2Compliant();
542 m_isErrorGeneratedOnOutOfBoundsAccesses = m_context->getExtensions()->isEnabled("GL_CHROMIUM_strict_attribs");
543 m_isResourceSafe = m_context->getExtensions()->isEnabled("GL_CHROMIUM_resource_safe");
544 if (m_isGLES2Compliant) {
545 m_isGLES2NPOTStrict = !m_context->getExtensions()->isEnabled("GL_OES_texture_npot");
546 m_isDepthStencilSupported = m_context->getExtensions()->isEnabled("GL_OES_packed_depth_stencil");
548 m_isGLES2NPOTStrict = !m_context->getExtensions()->isEnabled("GL_ARB_texture_non_power_of_two");
549 m_isDepthStencilSupported = m_context->getExtensions()->isEnabled("GL_EXT_packed_depth_stencil");
553 bool WebGLRenderingContext::allowPrivilegedExtensions() const
555 Page* p = canvas()->document()->page();
556 if (p && p->settings())
557 return p->settings()->privilegedWebGLExtensionsEnabled();
561 void WebGLRenderingContext::addCompressedTextureFormat(GC3Denum format)
563 if (!m_compressedTextureFormats.contains(format))
564 m_compressedTextureFormats.append(format);
567 WebGLRenderingContext::~WebGLRenderingContext()
569 // Remove all references to WebGLObjects so if they are the last reference
570 // they will be freed before the last context is removed from the context group.
571 m_boundArrayBuffer = 0;
572 m_defaultVertexArrayObject = 0;
573 m_boundVertexArrayObject = 0;
574 m_vertexAttrib0Buffer = 0;
575 m_currentProgram = 0;
576 m_framebufferBinding = 0;
577 m_renderbufferBinding = 0;
579 for (size_t i = 0; i < m_textureUnits.size(); ++i) {
580 m_textureUnits[i].m_texture2DBinding = 0;
581 m_textureUnits[i].m_textureCubeMapBinding = 0;
584 m_blackTexture2D = 0;
585 m_blackTextureCubeMap = 0;
587 detachAndRemoveAllObjects();
588 m_context->setContextLostCallback(nullptr);
589 m_context->setErrorMessageCallback(nullptr);
590 m_contextGroup->removeContext(this);
593 void WebGLRenderingContext::markContextChanged()
595 if (m_framebufferBinding)
598 m_context->markContextChanged();
600 m_layerCleared = false;
601 #if USE(ACCELERATED_COMPOSITING)
602 RenderBox* renderBox = canvas()->renderBox();
603 if (renderBox && renderBox->hasAcceleratedCompositing()) {
604 m_markedCanvasDirty = true;
605 renderBox->contentChanged(CanvasChanged);
608 if (!m_markedCanvasDirty) {
609 m_markedCanvasDirty = true;
610 canvas()->didDraw(FloatRect(FloatPoint(0, 0), clampedCanvasSize()));
612 #if USE(ACCELERATED_COMPOSITING)
617 bool WebGLRenderingContext::clearIfComposited(GC3Dbitfield mask)
622 if (!m_context->layerComposited() || m_layerCleared
623 || m_attributes.preserveDrawingBuffer || (mask && m_framebufferBinding))
626 RefPtr<WebGLContextAttributes> contextAttributes = getContextAttributes();
628 // Determine if it's possible to combine the clear the user asked for and this clear.
629 bool combinedClear = mask && !m_scissorEnabled;
631 m_context->disable(GraphicsContext3D::SCISSOR_TEST);
632 if (combinedClear && (mask & GraphicsContext3D::COLOR_BUFFER_BIT))
633 m_context->clearColor(m_colorMask[0] ? m_clearColor[0] : 0,
634 m_colorMask[1] ? m_clearColor[1] : 0,
635 m_colorMask[2] ? m_clearColor[2] : 0,
636 m_colorMask[3] ? m_clearColor[3] : 0);
638 m_context->clearColor(0, 0, 0, 0);
639 m_context->colorMask(true, true, true, true);
640 GC3Dbitfield clearMask = GraphicsContext3D::COLOR_BUFFER_BIT;
641 if (contextAttributes->depth()) {
642 if (!combinedClear || !m_depthMask || !(mask & GraphicsContext3D::DEPTH_BUFFER_BIT))
643 m_context->clearDepth(1.0f);
644 clearMask |= GraphicsContext3D::DEPTH_BUFFER_BIT;
645 m_context->depthMask(true);
647 if (contextAttributes->stencil()) {
648 if (combinedClear && (mask & GraphicsContext3D::STENCIL_BUFFER_BIT))
649 m_context->clearStencil(m_clearStencil & m_stencilMask);
651 m_context->clearStencil(0);
652 clearMask |= GraphicsContext3D::STENCIL_BUFFER_BIT;
653 m_context->stencilMaskSeparate(GraphicsContext3D::FRONT, 0xFFFFFFFF);
656 m_drawingBuffer->clearFramebuffers(clearMask);
658 if (m_framebufferBinding)
659 m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, 0);
660 m_context->clear(clearMask);
663 restoreStateAfterClear();
664 if (m_framebufferBinding)
665 m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, objectOrZero(m_framebufferBinding.get()));
666 m_layerCleared = true;
668 return combinedClear;
671 void WebGLRenderingContext::restoreStateAfterClear()
673 // Restore the state that the context set.
674 if (m_scissorEnabled)
675 m_context->enable(GraphicsContext3D::SCISSOR_TEST);
676 m_context->clearColor(m_clearColor[0], m_clearColor[1],
677 m_clearColor[2], m_clearColor[3]);
678 m_context->colorMask(m_colorMask[0], m_colorMask[1],
679 m_colorMask[2], m_colorMask[3]);
680 m_context->clearDepth(m_clearDepth);
681 m_context->clearStencil(m_clearStencil);
682 m_context->stencilMaskSeparate(GraphicsContext3D::FRONT, m_stencilMask);
683 m_context->depthMask(m_depthMask);
686 void WebGLRenderingContext::markLayerComposited()
688 m_context->markLayerComposited();
691 void WebGLRenderingContext::paintRenderingResultsToCanvas()
693 // Until the canvas is written to by the application, the clear that
694 // happened after it was composited should be ignored by the compositor.
695 if (m_context->layerComposited() && !m_attributes.preserveDrawingBuffer) {
696 m_context->paintCompositedResultsToCanvas(canvas()->buffer());
698 #if USE(ACCELERATED_COMPOSITING) && PLATFORM(CHROMIUM)
700 m_drawingBuffer->paintCompositedResultsToCanvas(canvas()->buffer());
703 canvas()->makePresentationCopy();
705 canvas()->clearPresentationCopy();
708 if (!m_markedCanvasDirty && !m_layerCleared)
711 canvas()->clearCopiedImage();
712 m_markedCanvasDirty = false;
715 m_drawingBuffer->commit();
716 m_context->paintRenderingResultsToCanvas(canvas()->buffer(), m_drawingBuffer.get());
718 if (m_drawingBuffer) {
719 if (m_framebufferBinding)
720 m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, objectOrZero(m_framebufferBinding.get()));
722 m_drawingBuffer->bind();
726 PassRefPtr<ImageData> WebGLRenderingContext::paintRenderingResultsToImageData()
730 m_drawingBuffer->commit();
731 RefPtr<ImageData> imageData = m_context->paintRenderingResultsToImageData(m_drawingBuffer.get());
733 if (m_drawingBuffer) {
734 if (m_framebufferBinding)
735 m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, objectOrZero(m_framebufferBinding.get()));
737 m_drawingBuffer->bind();
743 void WebGLRenderingContext::reshape(int width, int height)
745 // This is an approximation because at WebGLRenderingContext level we don't
746 // know if the underlying FBO uses textures or renderbuffers.
747 GC3Dint maxSize = std::min(m_maxTextureSize, m_maxRenderbufferSize);
748 // Limit drawing buffer size to 4k to avoid memory exhaustion.
749 const int sizeUpperLimit = 4096;
750 maxSize = std::min(maxSize, sizeUpperLimit);
751 GC3Dint maxWidth = std::min(maxSize, m_maxViewportDims[0]);
752 GC3Dint maxHeight = std::min(maxSize, m_maxViewportDims[1]);
753 width = clamp(width, 1, maxWidth);
754 height = clamp(height, 1, maxHeight);
757 #if USE(ACCELERATED_COMPOSITING)
758 RenderBox* renderBox = canvas()->renderBox();
759 if (renderBox && renderBox->hasAcceleratedCompositing())
760 renderBox->contentChanged(CanvasChanged);
762 m_needsUpdate = false;
765 // We don't have to mark the canvas as dirty, since the newly created image buffer will also start off
766 // clear (and this matches what reshape will do).
767 if (m_drawingBuffer) {
768 m_drawingBuffer->reset(IntSize(width, height));
769 restoreStateAfterClear();
771 m_context->reshape(width, height);
773 m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, objectOrZero(m_textureUnits[m_activeTextureUnit].m_texture2DBinding.get()));
774 m_context->bindRenderbuffer(GraphicsContext3D::RENDERBUFFER, objectOrZero(m_renderbufferBinding.get()));
775 if (m_framebufferBinding)
776 m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, objectOrZero(m_framebufferBinding.get()));
779 int WebGLRenderingContext::drawingBufferWidth() const
782 return m_drawingBuffer->size().width();
784 return m_context->getInternalFramebufferSize().width();
787 int WebGLRenderingContext::drawingBufferHeight() const
790 return m_drawingBuffer->size().height();
792 return m_context->getInternalFramebufferSize().height();
795 unsigned int WebGLRenderingContext::sizeInBytes(GC3Denum type)
798 case GraphicsContext3D::BYTE:
799 return sizeof(GC3Dbyte);
800 case GraphicsContext3D::UNSIGNED_BYTE:
801 return sizeof(GC3Dubyte);
802 case GraphicsContext3D::SHORT:
803 return sizeof(GC3Dshort);
804 case GraphicsContext3D::UNSIGNED_SHORT:
805 return sizeof(GC3Dushort);
806 case GraphicsContext3D::INT:
807 return sizeof(GC3Dint);
808 case GraphicsContext3D::UNSIGNED_INT:
809 return sizeof(GC3Duint);
810 case GraphicsContext3D::FLOAT:
811 return sizeof(GC3Dfloat);
813 ASSERT_NOT_REACHED();
817 void WebGLRenderingContext::activeTexture(GC3Denum texture, ExceptionCode& ec)
822 if (texture - GraphicsContext3D::TEXTURE0 >= m_textureUnits.size()) {
823 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "activeTexture", "texture unit out of range");
826 m_activeTextureUnit = texture - GraphicsContext3D::TEXTURE0;
827 m_context->activeTexture(texture);
830 m_drawingBuffer->setActiveTextureUnit(texture);
832 cleanupAfterGraphicsCall(false);
835 void WebGLRenderingContext::attachShader(WebGLProgram* program, WebGLShader* shader, ExceptionCode& ec)
838 if (isContextLost() || !validateWebGLObject("attachShader", program) || !validateWebGLObject("attachShader", shader))
840 if (!program->attachShader(shader)) {
841 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "attachShader", "shader attachment already has shader");
844 m_context->attachShader(objectOrZero(program), objectOrZero(shader));
845 shader->onAttached();
846 cleanupAfterGraphicsCall(false);
849 void WebGLRenderingContext::bindAttribLocation(WebGLProgram* program, GC3Duint index, const String& name, ExceptionCode& ec)
852 if (isContextLost() || !validateWebGLObject("bindAttribLocation", program))
854 if (!validateLocationLength("bindAttribLocation", name))
856 if (!validateString("bindAttribLocation", name))
858 if (isPrefixReserved(name)) {
859 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "bindAttribLocation", "reserved prefix");
862 if (index >= m_maxVertexAttribs) {
863 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "bindAttribLocation", "index out of range");
866 m_context->bindAttribLocation(objectOrZero(program), index, name);
867 cleanupAfterGraphicsCall(false);
870 bool WebGLRenderingContext::checkObjectToBeBound(const char* functionName, WebGLObject* object, bool& deleted)
876 if (!object->validate(contextGroup(), this)) {
877 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "object not from this context");
880 deleted = !object->object();
885 void WebGLRenderingContext::bindBuffer(GC3Denum target, WebGLBuffer* buffer, ExceptionCode& ec)
889 if (!checkObjectToBeBound("bindBuffer", buffer, deleted))
893 if (buffer && buffer->getTarget() && buffer->getTarget() != target) {
894 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "bindBuffer", "buffers can not be used with multiple targets");
897 if (target == GraphicsContext3D::ARRAY_BUFFER)
898 m_boundArrayBuffer = buffer;
899 else if (target == GraphicsContext3D::ELEMENT_ARRAY_BUFFER)
900 m_boundVertexArrayObject->setElementArrayBuffer(buffer);
902 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "bindBuffer", "invalid target");
906 m_context->bindBuffer(target, objectOrZero(buffer));
908 buffer->setTarget(target);
909 cleanupAfterGraphicsCall(false);
912 void WebGLRenderingContext::bindFramebuffer(GC3Denum target, WebGLFramebuffer* buffer, ExceptionCode& ec)
916 if (!checkObjectToBeBound("bindFramebuffer", buffer, deleted))
920 if (target != GraphicsContext3D::FRAMEBUFFER) {
921 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "bindFramebuffer", "invalid target");
924 m_framebufferBinding = buffer;
926 m_drawingBuffer->setFramebufferBinding(objectOrZero(m_framebufferBinding.get()));
927 if (!m_framebufferBinding && m_drawingBuffer) {
928 // Instead of binding fb 0, bind the drawing buffer.
929 m_drawingBuffer->bind();
931 m_context->bindFramebuffer(target, objectOrZero(buffer));
933 buffer->setHasEverBeenBound();
935 cleanupAfterGraphicsCall(false);
938 void WebGLRenderingContext::bindRenderbuffer(GC3Denum target, WebGLRenderbuffer* renderBuffer, ExceptionCode& ec)
942 if (!checkObjectToBeBound("bindRenderbuffer", renderBuffer, deleted))
946 if (target != GraphicsContext3D::RENDERBUFFER) {
947 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "bindRenderbuffer", "invalid target");
950 m_renderbufferBinding = renderBuffer;
951 m_context->bindRenderbuffer(target, objectOrZero(renderBuffer));
953 renderBuffer->setHasEverBeenBound();
954 cleanupAfterGraphicsCall(false);
957 void WebGLRenderingContext::bindTexture(GC3Denum target, WebGLTexture* texture, ExceptionCode& ec)
961 if (!checkObjectToBeBound("bindTexture", texture, deleted))
965 if (texture && texture->getTarget() && texture->getTarget() != target) {
966 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "bindTexture", "textures can not be used with multiple targets");
969 GC3Dint maxLevel = 0;
970 if (target == GraphicsContext3D::TEXTURE_2D) {
971 m_textureUnits[m_activeTextureUnit].m_texture2DBinding = texture;
972 maxLevel = m_maxTextureLevel;
974 if (m_drawingBuffer && !m_activeTextureUnit)
975 m_drawingBuffer->setTexture2DBinding(objectOrZero(texture));
977 } else if (target == GraphicsContext3D::TEXTURE_CUBE_MAP) {
978 m_textureUnits[m_activeTextureUnit].m_textureCubeMapBinding = texture;
979 maxLevel = m_maxCubeMapTextureLevel;
981 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "bindTexture", "invalid target");
984 m_context->bindTexture(target, objectOrZero(texture));
986 texture->setTarget(target, maxLevel);
988 // Note: previously we used to automatically set the TEXTURE_WRAP_R
989 // repeat mode to CLAMP_TO_EDGE for cube map textures, because OpenGL
990 // ES 2.0 doesn't expose this flag (a bug in the specification) and
991 // otherwise the application has no control over the seams in this
992 // dimension. However, it appears that supporting this properly on all
993 // platforms is fairly involved (will require a HashMap from texture ID
994 // in all ports), and we have not had any complaints, so the logic has
997 cleanupAfterGraphicsCall(false);
1000 void WebGLRenderingContext::blendColor(GC3Dfloat red, GC3Dfloat green, GC3Dfloat blue, GC3Dfloat alpha)
1002 if (isContextLost())
1004 m_context->blendColor(red, green, blue, alpha);
1005 cleanupAfterGraphicsCall(false);
1008 void WebGLRenderingContext::blendEquation(GC3Denum mode)
1010 if (isContextLost() || !validateBlendEquation("blendEquation", mode))
1012 m_context->blendEquation(mode);
1013 cleanupAfterGraphicsCall(false);
1016 void WebGLRenderingContext::blendEquationSeparate(GC3Denum modeRGB, GC3Denum modeAlpha)
1018 if (isContextLost() || !validateBlendEquation("blendEquation", modeRGB) || !validateBlendEquation("blendEquation", modeAlpha))
1020 m_context->blendEquationSeparate(modeRGB, modeAlpha);
1021 cleanupAfterGraphicsCall(false);
1025 void WebGLRenderingContext::blendFunc(GC3Denum sfactor, GC3Denum dfactor)
1027 if (isContextLost() || !validateBlendFuncFactors("blendFunc", sfactor, dfactor))
1029 m_context->blendFunc(sfactor, dfactor);
1030 cleanupAfterGraphicsCall(false);
1033 void WebGLRenderingContext::blendFuncSeparate(GC3Denum srcRGB, GC3Denum dstRGB, GC3Denum srcAlpha, GC3Denum dstAlpha)
1035 // Note: Alpha does not have the same restrictions as RGB.
1036 if (isContextLost() || !validateBlendFuncFactors("blendFunc", srcRGB, dstRGB))
1038 m_context->blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha);
1039 cleanupAfterGraphicsCall(false);
1042 void WebGLRenderingContext::bufferData(GC3Denum target, long long size, GC3Denum usage, ExceptionCode& ec)
1045 if (isContextLost())
1047 WebGLBuffer* buffer = validateBufferDataParameters("bufferData", target, usage);
1051 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "bufferData", "size < 0");
1054 if (!isErrorGeneratedOnOutOfBoundsAccesses()) {
1055 if (!buffer->associateBufferData(static_cast<GC3Dsizeiptr>(size))) {
1056 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "bufferData", "invalid buffer");
1061 m_context->bufferData(target, static_cast<GC3Dsizeiptr>(size), usage);
1062 cleanupAfterGraphicsCall(false);
1065 void WebGLRenderingContext::bufferData(GC3Denum target, ArrayBuffer* data, GC3Denum usage, ExceptionCode& ec)
1068 if (isContextLost())
1070 WebGLBuffer* buffer = validateBufferDataParameters("bufferData", target, usage);
1074 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "bufferData", "no data");
1077 if (!isErrorGeneratedOnOutOfBoundsAccesses()) {
1078 if (!buffer->associateBufferData(data)) {
1079 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "bufferData", "invalid buffer");
1084 m_context->bufferData(target, data->byteLength(), data->data(), usage);
1085 cleanupAfterGraphicsCall(false);
1088 void WebGLRenderingContext::bufferData(GC3Denum target, ArrayBufferView* data, GC3Denum usage, ExceptionCode& ec)
1091 if (isContextLost())
1093 WebGLBuffer* buffer = validateBufferDataParameters("bufferData", target, usage);
1097 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "bufferData", "no data");
1100 if (!isErrorGeneratedOnOutOfBoundsAccesses()) {
1101 if (!buffer->associateBufferData(data)) {
1102 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "bufferData", "invalid buffer");
1107 m_context->bufferData(target, data->byteLength(), data->baseAddress(), usage);
1108 cleanupAfterGraphicsCall(false);
1111 void WebGLRenderingContext::bufferSubData(GC3Denum target, long long offset, ArrayBuffer* data, ExceptionCode& ec)
1114 if (isContextLost())
1116 WebGLBuffer* buffer = validateBufferDataParameters("bufferSubData", target, GraphicsContext3D::STATIC_DRAW);
1120 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "bufferSubData", "offset < 0");
1125 if (!isErrorGeneratedOnOutOfBoundsAccesses()) {
1126 if (!buffer->associateBufferSubData(static_cast<GC3Dintptr>(offset), data)) {
1127 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "bufferSubData", "offset out of range");
1132 m_context->bufferSubData(target, static_cast<GC3Dintptr>(offset), data->byteLength(), data->data());
1133 cleanupAfterGraphicsCall(false);
1136 void WebGLRenderingContext::bufferSubData(GC3Denum target, long long offset, ArrayBufferView* data, ExceptionCode& ec)
1139 if (isContextLost())
1141 WebGLBuffer* buffer = validateBufferDataParameters("bufferSubData", target, GraphicsContext3D::STATIC_DRAW);
1145 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "bufferSubData", "offset < 0");
1150 if (!isErrorGeneratedOnOutOfBoundsAccesses()) {
1151 if (!buffer->associateBufferSubData(static_cast<GC3Dintptr>(offset), data)) {
1152 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "bufferSubData", "offset out of range");
1157 m_context->bufferSubData(target, static_cast<GC3Dintptr>(offset), data->byteLength(), data->baseAddress());
1158 cleanupAfterGraphicsCall(false);
1161 GC3Denum WebGLRenderingContext::checkFramebufferStatus(GC3Denum target)
1163 if (isContextLost())
1164 return GraphicsContext3D::FRAMEBUFFER_UNSUPPORTED;
1165 if (target != GraphicsContext3D::FRAMEBUFFER) {
1166 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "checkFramebufferStatus", "invalid target");
1169 if (!m_framebufferBinding || !m_framebufferBinding->object())
1170 return GraphicsContext3D::FRAMEBUFFER_COMPLETE;
1171 const char* reason = "framebuffer incomplete";
1172 GC3Denum result = m_framebufferBinding->checkStatus(&reason);
1173 if (result != GraphicsContext3D::FRAMEBUFFER_COMPLETE) {
1174 printGLWarningToConsole("checkFramebufferStatus", reason);
1177 result = m_context->checkFramebufferStatus(target);
1178 cleanupAfterGraphicsCall(false);
1182 void WebGLRenderingContext::clear(GC3Dbitfield mask)
1184 if (isContextLost())
1186 if (mask & ~(GraphicsContext3D::COLOR_BUFFER_BIT | GraphicsContext3D::DEPTH_BUFFER_BIT | GraphicsContext3D::STENCIL_BUFFER_BIT)) {
1187 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "clear", "invalid mask");
1190 const char* reason = "framebuffer incomplete";
1191 if (m_framebufferBinding && !m_framebufferBinding->onAccess(graphicsContext3D(), !isResourceSafe(), &reason)) {
1192 synthesizeGLError(GraphicsContext3D::INVALID_FRAMEBUFFER_OPERATION, "clear", reason);
1195 if (!clearIfComposited(mask))
1196 m_context->clear(mask);
1197 cleanupAfterGraphicsCall(true);
1200 void WebGLRenderingContext::clearColor(GC3Dfloat r, GC3Dfloat g, GC3Dfloat b, GC3Dfloat a)
1202 if (isContextLost())
1212 m_clearColor[0] = r;
1213 m_clearColor[1] = g;
1214 m_clearColor[2] = b;
1215 m_clearColor[3] = a;
1216 m_context->clearColor(r, g, b, a);
1217 cleanupAfterGraphicsCall(false);
1220 void WebGLRenderingContext::clearDepth(GC3Dfloat depth)
1222 if (isContextLost())
1224 m_clearDepth = depth;
1225 m_context->clearDepth(depth);
1226 cleanupAfterGraphicsCall(false);
1229 void WebGLRenderingContext::clearStencil(GC3Dint s)
1231 if (isContextLost())
1234 m_context->clearStencil(s);
1235 cleanupAfterGraphicsCall(false);
1238 void WebGLRenderingContext::colorMask(GC3Dboolean red, GC3Dboolean green, GC3Dboolean blue, GC3Dboolean alpha)
1240 if (isContextLost())
1242 m_colorMask[0] = red;
1243 m_colorMask[1] = green;
1244 m_colorMask[2] = blue;
1245 m_colorMask[3] = alpha;
1246 m_context->colorMask(red, green, blue, alpha);
1247 cleanupAfterGraphicsCall(false);
1250 void WebGLRenderingContext::compileShader(WebGLShader* shader, ExceptionCode& ec)
1253 if (isContextLost() || !validateWebGLObject("compileShader", shader))
1255 m_context->compileShader(objectOrZero(shader));
1256 cleanupAfterGraphicsCall(false);
1259 void WebGLRenderingContext::compressedTexImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dsizei width,
1260 GC3Dsizei height, GC3Dint border, ArrayBufferView* data)
1262 if (isContextLost())
1264 if (!validateTexFuncLevel("compressedTexImage2D", target, level))
1267 if (!validateCompressedTexFormat(internalformat)) {
1268 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "compressedTexImage2D", "invalid internalformat");
1272 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "compressedTexImage2D", "border not 0");
1275 if (!validateCompressedTexDimensions("compressedTexImage2D", level, width, height, internalformat))
1277 if (!validateCompressedTexFuncData("compressedTexImage2D", width, height, internalformat, data))
1280 WebGLTexture* tex = validateTextureBinding("compressedTexImage2D", target, true);
1283 if (!isGLES2NPOTStrict()) {
1284 if (level && WebGLTexture::isNPOT(width, height)) {
1285 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "compressedTexImage2D", "level > 0 not power of 2");
1289 graphicsContext3D()->compressedTexImage2D(target, level, internalformat, width, height,
1290 border, data->byteLength(), data->baseAddress());
1291 tex->setLevelInfo(target, level, internalformat, width, height, GraphicsContext3D::UNSIGNED_BYTE);
1292 cleanupAfterGraphicsCall(false);
1295 void WebGLRenderingContext::compressedTexSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
1296 GC3Dsizei width, GC3Dsizei height, GC3Denum format, ArrayBufferView* data)
1298 if (isContextLost())
1300 if (!validateTexFuncLevel("compressedTexSubImage2D", target, level))
1302 if (!validateCompressedTexFormat(format)) {
1303 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "compressedTexSubImage2D", "invalid format");
1306 if (!validateCompressedTexFuncData("compressedTexSubImage2D", width, height, format, data))
1309 WebGLTexture* tex = validateTextureBinding("compressedTexSubImage2D", target, true);
1313 if (format != tex->getInternalFormat(target, level)) {
1314 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "compressedTexSubImage2D", "format does not match texture format");
1318 if (!validateCompressedTexSubDimensions("compressedTexSubImage2D", target, level, xoffset, yoffset, width, height, format, tex))
1321 graphicsContext3D()->compressedTexSubImage2D(target, level, xoffset, yoffset,
1322 width, height, format, data->byteLength(), data->baseAddress());
1323 cleanupAfterGraphicsCall(false);
1326 bool WebGLRenderingContext::validateSettableTexFormat(const char* functionName, GC3Denum format)
1328 if (GraphicsContext3D::getClearBitsByFormat(format) & (GraphicsContext3D::DEPTH_BUFFER_BIT | GraphicsContext3D::STENCIL_BUFFER_BIT)) {
1329 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "format can not be set, only rendered to");
1335 void WebGLRenderingContext::copyTexImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height, GC3Dint border)
1337 if (isContextLost())
1339 if (!validateTexFuncParameters("copyTexImage2D", NotTexSubImage2D, target, level, internalformat, width, height, border, internalformat, GraphicsContext3D::UNSIGNED_BYTE))
1341 if (!validateSettableTexFormat("copyTexImage2D", internalformat))
1343 WebGLTexture* tex = validateTextureBinding("copyTexImage2D", target, true);
1346 if (!isTexInternalFormatColorBufferCombinationValid(internalformat, getBoundFramebufferColorFormat())) {
1347 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "copyTexImage2D", "framebuffer is incompatible format");
1350 if (!isGLES2NPOTStrict() && level && WebGLTexture::isNPOT(width, height)) {
1351 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "copyTexImage2D", "level > 0 not power of 2");
1354 const char* reason = "framebuffer incomplete";
1355 if (m_framebufferBinding && !m_framebufferBinding->onAccess(graphicsContext3D(), !isResourceSafe(), &reason)) {
1356 synthesizeGLError(GraphicsContext3D::INVALID_FRAMEBUFFER_OPERATION, "copyTexImage2D", reason);
1359 clearIfComposited();
1360 if (isResourceSafe()) {
1361 ScopedDrawingBufferBinder binder(m_drawingBuffer.get(), m_framebufferBinding.get());
1362 m_context->copyTexImage2D(target, level, internalformat, x, y, width, height, border);
1364 ScopedDrawingBufferBinder binder(m_drawingBuffer.get(), m_framebufferBinding.get());
1365 GC3Dint clippedX, clippedY;
1366 GC3Dsizei clippedWidth, clippedHeight;
1367 if (clip2D(x, y, width, height, getBoundFramebufferWidth(), getBoundFramebufferHeight(), &clippedX, &clippedY, &clippedWidth, &clippedHeight)) {
1368 m_context->texImage2DResourceSafe(target, level, internalformat, width, height, border,
1369 internalformat, GraphicsContext3D::UNSIGNED_BYTE, m_unpackAlignment);
1370 if (clippedWidth > 0 && clippedHeight > 0) {
1371 m_context->copyTexSubImage2D(target, level, clippedX - x, clippedY - y,
1372 clippedX, clippedY, clippedWidth, clippedHeight);
1375 m_context->copyTexImage2D(target, level, internalformat, x, y, width, height, border);
1377 // FIXME: if the framebuffer is not complete, none of the below should be executed.
1378 tex->setLevelInfo(target, level, internalformat, width, height, GraphicsContext3D::UNSIGNED_BYTE);
1379 cleanupAfterGraphicsCall(false);
1382 void WebGLRenderingContext::copyTexSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height)
1384 if (isContextLost())
1386 if (!validateTexFuncLevel("copyTexSubImage2D", target, level))
1388 WebGLTexture* tex = validateTextureBinding("copyTexSubImage2D", target, true);
1391 if (!validateSize("copyTexSubImage2D", xoffset, yoffset) || !validateSize("copyTexSubImage2D", width, height))
1393 if (xoffset + width > tex->getWidth(target, level) || yoffset + height > tex->getHeight(target, level)) {
1394 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "copyTexSubImage2D", "rectangle out of range");
1397 GC3Denum internalformat = tex->getInternalFormat(target, level);
1398 if (!validateSettableTexFormat("copyTexSubImage2D", internalformat))
1400 if (!isTexInternalFormatColorBufferCombinationValid(internalformat, getBoundFramebufferColorFormat())) {
1401 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "copyTexSubImage2D", "framebuffer is incompatible format");
1404 const char* reason = "framebuffer incomplete";
1405 if (m_framebufferBinding && !m_framebufferBinding->onAccess(graphicsContext3D(), !isResourceSafe(), &reason)) {
1406 synthesizeGLError(GraphicsContext3D::INVALID_FRAMEBUFFER_OPERATION, "copyTexSubImage2D", reason);
1409 clearIfComposited();
1410 if (isResourceSafe()) {
1411 ScopedDrawingBufferBinder binder(m_drawingBuffer.get(), m_framebufferBinding.get());
1412 m_context->copyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height);
1414 GC3Dint clippedX, clippedY;
1415 GC3Dsizei clippedWidth, clippedHeight;
1416 if (clip2D(x, y, width, height, getBoundFramebufferWidth(), getBoundFramebufferHeight(), &clippedX, &clippedY, &clippedWidth, &clippedHeight)) {
1417 GC3Denum format = tex->getInternalFormat(target, level);
1418 GC3Denum type = tex->getType(target, level);
1419 OwnArrayPtr<unsigned char> zero;
1420 if (width && height) {
1422 GC3Denum error = m_context->computeImageSizeInBytes(format, type, width, height, m_unpackAlignment, &size, 0);
1423 if (error != GraphicsContext3D::NO_ERROR) {
1424 synthesizeGLError(error, "copyTexSubImage2D", "bad dimensions");
1427 zero = adoptArrayPtr(new unsigned char[size]);
1429 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "copyTexSubImage2D", "out of memory");
1432 memset(zero.get(), 0, size);
1434 m_context->texSubImage2D(target, level, xoffset, yoffset, width, height, format, type, zero.get());
1435 if (clippedWidth > 0 && clippedHeight > 0) {
1436 ScopedDrawingBufferBinder binder(m_drawingBuffer.get(), m_framebufferBinding.get());
1437 m_context->copyTexSubImage2D(target, level, xoffset + clippedX - x, yoffset + clippedY - y,
1438 clippedX, clippedY, clippedWidth, clippedHeight);
1441 ScopedDrawingBufferBinder binder(m_drawingBuffer.get(), m_framebufferBinding.get());
1442 m_context->copyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height);
1445 cleanupAfterGraphicsCall(false);
1448 PassRefPtr<WebGLBuffer> WebGLRenderingContext::createBuffer()
1450 if (isContextLost())
1452 RefPtr<WebGLBuffer> o = WebGLBuffer::create(this);
1453 addSharedObject(o.get());
1457 PassRefPtr<WebGLFramebuffer> WebGLRenderingContext::createFramebuffer()
1459 if (isContextLost())
1461 RefPtr<WebGLFramebuffer> o = WebGLFramebuffer::create(this);
1462 addContextObject(o.get());
1466 PassRefPtr<WebGLTexture> WebGLRenderingContext::createTexture()
1468 if (isContextLost())
1470 RefPtr<WebGLTexture> o = WebGLTexture::create(this);
1471 addSharedObject(o.get());
1475 PassRefPtr<WebGLProgram> WebGLRenderingContext::createProgram()
1477 if (isContextLost())
1479 RefPtr<WebGLProgram> o = WebGLProgram::create(this);
1480 addSharedObject(o.get());
1484 PassRefPtr<WebGLRenderbuffer> WebGLRenderingContext::createRenderbuffer()
1486 if (isContextLost())
1488 RefPtr<WebGLRenderbuffer> o = WebGLRenderbuffer::create(this);
1489 addSharedObject(o.get());
1493 PassRefPtr<WebGLShader> WebGLRenderingContext::createShader(GC3Denum type, ExceptionCode& ec)
1496 if (isContextLost())
1498 if (type != GraphicsContext3D::VERTEX_SHADER && type != GraphicsContext3D::FRAGMENT_SHADER) {
1499 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "createShader", "invalid shader type");
1503 RefPtr<WebGLShader> o = WebGLShader::create(this, type);
1504 addSharedObject(o.get());
1508 void WebGLRenderingContext::cullFace(GC3Denum mode)
1510 if (isContextLost())
1512 m_context->cullFace(mode);
1513 cleanupAfterGraphicsCall(false);
1516 bool WebGLRenderingContext::deleteObject(WebGLObject* object)
1518 if (isContextLost() || !object)
1520 if (!object->validate(contextGroup(), this)) {
1521 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "delete", "object does not belong to this context");
1524 if (object->object())
1525 // We need to pass in context here because we want
1526 // things in this context unbound.
1527 object->deleteObject(graphicsContext3D());
1531 void WebGLRenderingContext::deleteBuffer(WebGLBuffer* buffer)
1533 if (!deleteObject(buffer))
1535 if (m_boundArrayBuffer == buffer)
1536 m_boundArrayBuffer = 0;
1537 RefPtr<WebGLBuffer> elementArrayBuffer = m_boundVertexArrayObject->getElementArrayBuffer();
1538 if (elementArrayBuffer == buffer)
1539 m_boundVertexArrayObject->setElementArrayBuffer(0);
1540 if (!isGLES2Compliant()) {
1541 WebGLVertexArrayObjectOES::VertexAttribState& state = m_boundVertexArrayObject->getVertexAttribState(0);
1542 if (buffer == state.bufferBinding) {
1543 state.bufferBinding = m_vertexAttrib0Buffer;
1544 state.bytesPerElement = 0;
1546 state.type = GraphicsContext3D::FLOAT;
1547 state.normalized = false;
1549 state.originalStride = 0;
1555 void WebGLRenderingContext::deleteFramebuffer(WebGLFramebuffer* framebuffer)
1557 if (!deleteObject(framebuffer))
1559 if (framebuffer == m_framebufferBinding) {
1560 m_framebufferBinding = 0;
1561 if (m_drawingBuffer) {
1562 m_drawingBuffer->setFramebufferBinding(0);
1563 // Have to call bindFramebuffer here to bind back to internal fbo.
1564 m_drawingBuffer->bind();
1566 m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, 0);
1570 void WebGLRenderingContext::deleteProgram(WebGLProgram* program)
1572 deleteObject(program);
1573 // We don't reset m_currentProgram to 0 here because the deletion of the
1574 // current program is delayed.
1577 void WebGLRenderingContext::deleteRenderbuffer(WebGLRenderbuffer* renderbuffer)
1579 if (!deleteObject(renderbuffer))
1581 if (renderbuffer == m_renderbufferBinding)
1582 m_renderbufferBinding = 0;
1583 if (m_framebufferBinding)
1584 m_framebufferBinding->removeAttachmentFromBoundFramebuffer(renderbuffer);
1587 void WebGLRenderingContext::deleteShader(WebGLShader* shader)
1589 deleteObject(shader);
1592 void WebGLRenderingContext::deleteTexture(WebGLTexture* texture)
1594 if (!deleteObject(texture))
1596 for (size_t i = 0; i < m_textureUnits.size(); ++i) {
1597 if (texture == m_textureUnits[i].m_texture2DBinding)
1598 m_textureUnits[i].m_texture2DBinding = 0;
1599 if (texture == m_textureUnits[i].m_textureCubeMapBinding)
1600 m_textureUnits[i].m_textureCubeMapBinding = 0;
1602 if (m_framebufferBinding)
1603 m_framebufferBinding->removeAttachmentFromBoundFramebuffer(texture);
1606 void WebGLRenderingContext::depthFunc(GC3Denum func)
1608 if (isContextLost())
1610 m_context->depthFunc(func);
1611 cleanupAfterGraphicsCall(false);
1614 void WebGLRenderingContext::depthMask(GC3Dboolean flag)
1616 if (isContextLost())
1619 m_context->depthMask(flag);
1620 cleanupAfterGraphicsCall(false);
1623 void WebGLRenderingContext::depthRange(GC3Dfloat zNear, GC3Dfloat zFar)
1625 if (isContextLost())
1628 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "depthRange", "zNear > zFar");
1631 m_context->depthRange(zNear, zFar);
1632 cleanupAfterGraphicsCall(false);
1635 void WebGLRenderingContext::detachShader(WebGLProgram* program, WebGLShader* shader, ExceptionCode& ec)
1638 if (isContextLost() || !validateWebGLObject("detachShader", program) || !validateWebGLObject("detachShader", shader))
1640 if (!program->detachShader(shader)) {
1641 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "detachShader", "shader not attached");
1644 m_context->detachShader(objectOrZero(program), objectOrZero(shader));
1645 shader->onDetached(graphicsContext3D());
1646 cleanupAfterGraphicsCall(false);
1649 void WebGLRenderingContext::disable(GC3Denum cap)
1651 if (isContextLost() || !validateCapability("disable", cap))
1653 if (cap == GraphicsContext3D::STENCIL_TEST) {
1654 m_stencilEnabled = false;
1656 cleanupAfterGraphicsCall(false);
1659 if (cap == GraphicsContext3D::SCISSOR_TEST) {
1660 m_scissorEnabled = false;
1661 if (m_drawingBuffer)
1662 m_drawingBuffer->setScissorEnabled(m_scissorEnabled);
1664 m_context->disable(cap);
1665 cleanupAfterGraphicsCall(false);
1668 void WebGLRenderingContext::disableVertexAttribArray(GC3Duint index, ExceptionCode& ec)
1671 if (isContextLost())
1673 if (index >= m_maxVertexAttribs) {
1674 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "disableVertexAttribArray", "index out of range");
1678 WebGLVertexArrayObjectOES::VertexAttribState& state = m_boundVertexArrayObject->getVertexAttribState(index);
1679 state.enabled = false;
1681 if (index > 0 || isGLES2Compliant()) {
1682 m_context->disableVertexAttribArray(index);
1683 cleanupAfterGraphicsCall(false);
1687 bool WebGLRenderingContext::validateElementArraySize(GC3Dsizei count, GC3Denum type, GC3Dintptr offset)
1689 RefPtr<WebGLBuffer> elementArrayBuffer = m_boundVertexArrayObject->getElementArrayBuffer();
1691 if (!elementArrayBuffer)
1697 if (type == GraphicsContext3D::UNSIGNED_SHORT) {
1698 // For an unsigned short array, offset must be divisible by 2 for alignment reasons.
1702 // Make uoffset an element offset.
1705 GC3Dsizeiptr n = elementArrayBuffer->byteLength() / 2;
1706 if (offset > n || count > n - offset)
1708 } else if (type == GraphicsContext3D::UNSIGNED_BYTE) {
1709 GC3Dsizeiptr n = elementArrayBuffer->byteLength();
1710 if (offset > n || count > n - offset)
1716 bool WebGLRenderingContext::validateIndexArrayConservative(GC3Denum type, int& numElementsRequired)
1718 // Performs conservative validation by caching a maximum index of
1719 // the given type per element array buffer. If all of the bound
1720 // array buffers have enough elements to satisfy that maximum
1721 // index, skips the expensive per-draw-call iteration in
1722 // validateIndexArrayPrecise.
1724 RefPtr<WebGLBuffer> elementArrayBuffer = m_boundVertexArrayObject->getElementArrayBuffer();
1726 if (!elementArrayBuffer)
1729 GC3Dsizeiptr numElements = elementArrayBuffer->byteLength();
1730 // The case count==0 is already dealt with in drawElements before validateIndexArrayConservative.
1733 const ArrayBuffer* buffer = elementArrayBuffer->elementArrayBuffer();
1736 int maxIndex = elementArrayBuffer->getCachedMaxIndex(type);
1738 // Compute the maximum index in the entire buffer for the given type of index.
1740 case GraphicsContext3D::UNSIGNED_BYTE: {
1741 const GC3Dubyte* p = static_cast<const GC3Dubyte*>(buffer->data());
1742 for (GC3Dsizeiptr i = 0; i < numElements; i++)
1743 maxIndex = max(maxIndex, static_cast<int>(p[i]));
1746 case GraphicsContext3D::UNSIGNED_SHORT: {
1747 numElements /= sizeof(GC3Dushort);
1748 const GC3Dushort* p = static_cast<const GC3Dushort*>(buffer->data());
1749 for (GC3Dsizeiptr i = 0; i < numElements; i++)
1750 maxIndex = max(maxIndex, static_cast<int>(p[i]));
1756 elementArrayBuffer->setCachedMaxIndex(type, maxIndex);
1759 if (maxIndex >= 0) {
1760 // The number of required elements is one more than the maximum
1761 // index that will be accessed.
1762 numElementsRequired = maxIndex + 1;
1769 bool WebGLRenderingContext::validateIndexArrayPrecise(GC3Dsizei count, GC3Denum type, GC3Dintptr offset, int& numElementsRequired)
1771 ASSERT(count >= 0 && offset >= 0);
1774 RefPtr<WebGLBuffer> elementArrayBuffer = m_boundVertexArrayObject->getElementArrayBuffer();
1776 if (!elementArrayBuffer)
1780 numElementsRequired = 0;
1784 if (!elementArrayBuffer->elementArrayBuffer())
1787 unsigned long uoffset = offset;
1788 unsigned long n = count;
1790 if (type == GraphicsContext3D::UNSIGNED_SHORT) {
1791 // Make uoffset an element offset.
1792 uoffset /= sizeof(GC3Dushort);
1793 const GC3Dushort* p = static_cast<const GC3Dushort*>(elementArrayBuffer->elementArrayBuffer()->data()) + uoffset;
1799 } else if (type == GraphicsContext3D::UNSIGNED_BYTE) {
1800 const GC3Dubyte* p = static_cast<const GC3Dubyte*>(elementArrayBuffer->elementArrayBuffer()->data()) + uoffset;
1808 // Then set the last index in the index array and make sure it is valid.
1809 numElementsRequired = lastIndex + 1;
1810 return numElementsRequired > 0;
1813 bool WebGLRenderingContext::validateRenderingState(int numElementsRequired)
1815 if (!m_currentProgram)
1818 // Look in each enabled vertex attrib and check if they've been bound to a buffer.
1819 for (unsigned i = 0; i < m_maxVertexAttribs; ++i) {
1820 const WebGLVertexArrayObjectOES::VertexAttribState& state = m_boundVertexArrayObject->getVertexAttribState(i);
1822 && (!state.bufferBinding || !state.bufferBinding->object()))
1826 if (numElementsRequired <= 0)
1829 // Look in each consumed vertex attrib (by the current program) and find the smallest buffer size
1830 int smallestNumElements = INT_MAX;
1831 int numActiveAttribLocations = m_currentProgram->numActiveAttribLocations();
1832 for (int i = 0; i < numActiveAttribLocations; ++i) {
1833 int loc = m_currentProgram->getActiveAttribLocation(i);
1834 if (loc >= 0 && loc < static_cast<int>(m_maxVertexAttribs)) {
1835 const WebGLVertexArrayObjectOES::VertexAttribState& state = m_boundVertexArrayObject->getVertexAttribState(loc);
1836 if (state.enabled) {
1837 // Avoid off-by-one errors in numElements computation.
1838 // For the last element, we will only touch the data for the
1839 // element and nothing beyond it.
1840 int bytesRemaining = static_cast<int>(state.bufferBinding->byteLength() - state.offset);
1841 int numElements = 0;
1842 ASSERT(state.stride > 0);
1843 if (bytesRemaining >= state.bytesPerElement)
1844 numElements = 1 + (bytesRemaining - state.bytesPerElement) / state.stride;
1845 if (numElements < smallestNumElements)
1846 smallestNumElements = numElements;
1851 if (smallestNumElements == INT_MAX)
1852 smallestNumElements = 0;
1854 return numElementsRequired <= smallestNumElements;
1857 bool WebGLRenderingContext::validateWebGLObject(const char* functionName, WebGLObject* object)
1859 if (!object || !object->object()) {
1860 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "no object or object deleted");
1863 if (!object->validate(contextGroup(), this)) {
1864 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "object does not belong to this context");
1870 void WebGLRenderingContext::drawArrays(GC3Denum mode, GC3Dint first, GC3Dsizei count, ExceptionCode& ec)
1874 if (isContextLost() || !validateDrawMode("drawArrays", mode))
1877 if (!validateStencilSettings("drawArrays"))
1880 if (first < 0 || count < 0) {
1881 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "drawArrays", "first or count < 0");
1886 cleanupAfterGraphicsCall(true);
1890 if (!isErrorGeneratedOnOutOfBoundsAccesses()) {
1891 // Ensure we have a valid rendering state
1892 CheckedInt<GC3Dint> checkedFirst(first);
1893 CheckedInt<GC3Dint> checkedCount(count);
1894 CheckedInt<GC3Dint> checkedSum = checkedFirst + checkedCount;
1895 if (!checkedSum.valid() || !validateRenderingState(checkedSum.value())) {
1896 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "drawArrays", "attempt to access out of bounds arrays");
1900 if (!validateRenderingState(0)) {
1901 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "drawArrays", "attribs not setup correctly");
1906 const char* reason = "framebuffer incomplete";
1907 if (m_framebufferBinding && !m_framebufferBinding->onAccess(graphicsContext3D(), !isResourceSafe(), &reason)) {
1908 synthesizeGLError(GraphicsContext3D::INVALID_FRAMEBUFFER_OPERATION, "drawArrays", reason);
1912 clearIfComposited();
1914 bool vertexAttrib0Simulated = false;
1915 if (!isGLES2Compliant())
1916 vertexAttrib0Simulated = simulateVertexAttrib0(first + count - 1);
1917 if (!isGLES2NPOTStrict())
1918 handleNPOTTextures(true);
1919 m_context->drawArrays(mode, first, count);
1920 if (!isGLES2Compliant() && vertexAttrib0Simulated)
1921 restoreStatesAfterVertexAttrib0Simulation();
1922 if (!isGLES2NPOTStrict())
1923 handleNPOTTextures(false);
1924 cleanupAfterGraphicsCall(true);
1927 void WebGLRenderingContext::drawElements(GC3Denum mode, GC3Dsizei count, GC3Denum type, long long offset, ExceptionCode& ec)
1931 if (isContextLost() || !validateDrawMode("drawElements", mode))
1934 if (!validateStencilSettings("drawElements"))
1938 case GraphicsContext3D::UNSIGNED_BYTE:
1939 case GraphicsContext3D::UNSIGNED_SHORT:
1942 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "drawElements", "invalid type");
1946 if (count < 0 || offset < 0) {
1947 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "drawElements", "count or offset < 0");
1952 cleanupAfterGraphicsCall(true);
1956 if (!m_boundVertexArrayObject->getElementArrayBuffer()) {
1957 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "drawElements", "no ELEMENT_ARRAY_BUFFER bound");
1961 int numElements = 0;
1962 if (!isErrorGeneratedOnOutOfBoundsAccesses()) {
1963 // Ensure we have a valid rendering state
1964 if (!validateElementArraySize(count, type, static_cast<GC3Dintptr>(offset))) {
1965 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "drawElements", "request out of bounds for current ELEMENT_ARRAY_BUFFER");
1970 if (!validateIndexArrayConservative(type, numElements) || !validateRenderingState(numElements)) {
1971 if (!validateIndexArrayPrecise(count, type, static_cast<GC3Dintptr>(offset), numElements) || !validateRenderingState(numElements)) {
1972 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "drawElements", "attempt to access out of bounds arrays");
1977 if (!validateRenderingState(0)) {
1978 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "drawElements", "attribs not setup correctly");
1983 const char* reason = "framebuffer incomplete";
1984 if (m_framebufferBinding && !m_framebufferBinding->onAccess(graphicsContext3D(), !isResourceSafe(), &reason)) {
1985 synthesizeGLError(GraphicsContext3D::INVALID_FRAMEBUFFER_OPERATION, "drawElements", reason);
1988 clearIfComposited();
1990 bool vertexAttrib0Simulated = false;
1991 if (!isGLES2Compliant()) {
1993 validateIndexArrayPrecise(count, type, static_cast<GC3Dintptr>(offset), numElements);
1994 vertexAttrib0Simulated = simulateVertexAttrib0(numElements);
1996 if (!isGLES2NPOTStrict())
1997 handleNPOTTextures(true);
1998 m_context->drawElements(mode, count, type, static_cast<GC3Dintptr>(offset));
1999 if (!isGLES2Compliant() && vertexAttrib0Simulated)
2000 restoreStatesAfterVertexAttrib0Simulation();
2001 if (!isGLES2NPOTStrict())
2002 handleNPOTTextures(false);
2003 cleanupAfterGraphicsCall(true);
2006 void WebGLRenderingContext::enable(GC3Denum cap)
2008 if (isContextLost() || !validateCapability("enable", cap))
2010 if (cap == GraphicsContext3D::STENCIL_TEST) {
2011 m_stencilEnabled = true;
2013 cleanupAfterGraphicsCall(false);
2016 if (cap == GraphicsContext3D::SCISSOR_TEST) {
2017 m_scissorEnabled = true;
2018 if (m_drawingBuffer)
2019 m_drawingBuffer->setScissorEnabled(m_scissorEnabled);
2021 m_context->enable(cap);
2022 cleanupAfterGraphicsCall(false);
2025 void WebGLRenderingContext::enableVertexAttribArray(GC3Duint index, ExceptionCode& ec)
2028 if (isContextLost())
2030 if (index >= m_maxVertexAttribs) {
2031 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "enableVertexAttribArray", "index out of range");
2035 WebGLVertexArrayObjectOES::VertexAttribState& state = m_boundVertexArrayObject->getVertexAttribState(index);
2036 state.enabled = true;
2038 m_context->enableVertexAttribArray(index);
2039 cleanupAfterGraphicsCall(false);
2042 void WebGLRenderingContext::finish()
2044 if (isContextLost())
2046 m_context->finish();
2047 cleanupAfterGraphicsCall(false);
2050 void WebGLRenderingContext::flush()
2052 if (isContextLost())
2055 cleanupAfterGraphicsCall(false);
2058 void WebGLRenderingContext::framebufferRenderbuffer(GC3Denum target, GC3Denum attachment, GC3Denum renderbuffertarget, WebGLRenderbuffer* buffer, ExceptionCode& ec)
2061 if (isContextLost() || !validateFramebufferFuncParameters("framebufferRenderbuffer", target, attachment))
2063 if (renderbuffertarget != GraphicsContext3D::RENDERBUFFER) {
2064 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "framebufferRenderbuffer", "invalid target");
2067 if (buffer && !buffer->validate(contextGroup(), this)) {
2068 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "framebufferRenderbuffer", "no buffer or buffer not from this context");
2071 // Don't allow the default framebuffer to be mutated; all current
2072 // implementations use an FBO internally in place of the default
2074 if (!m_framebufferBinding || !m_framebufferBinding->object()) {
2075 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "framebufferRenderbuffer", "no framebuffer bound");
2078 Platform3DObject bufferObject = objectOrZero(buffer);
2079 switch (attachment) {
2080 case GraphicsContext3D::DEPTH_STENCIL_ATTACHMENT:
2081 m_context->framebufferRenderbuffer(target, GraphicsContext3D::DEPTH_ATTACHMENT, renderbuffertarget, bufferObject);
2082 m_context->framebufferRenderbuffer(target, GraphicsContext3D::STENCIL_ATTACHMENT, renderbuffertarget, bufferObject);
2084 case GraphicsContext3D::DEPTH_ATTACHMENT:
2085 m_context->framebufferRenderbuffer(target, attachment, renderbuffertarget, bufferObject);
2087 case GraphicsContext3D::STENCIL_ATTACHMENT:
2088 m_context->framebufferRenderbuffer(target, attachment, renderbuffertarget, bufferObject);
2091 m_context->framebufferRenderbuffer(target, attachment, renderbuffertarget, bufferObject);
2093 m_framebufferBinding->setAttachmentForBoundFramebuffer(attachment, buffer);
2095 cleanupAfterGraphicsCall(false);
2098 void WebGLRenderingContext::framebufferTexture2D(GC3Denum target, GC3Denum attachment, GC3Denum textarget, WebGLTexture* texture, GC3Dint level, ExceptionCode& ec)
2101 if (isContextLost() || !validateFramebufferFuncParameters("framebufferTexture2D", target, attachment))
2104 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "framebufferTexture2D", "level not 0");
2107 if (texture && !texture->validate(contextGroup(), this)) {
2108 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "framebufferTexture2D", "no texture or texture not from this context");
2111 // Don't allow the default framebuffer to be mutated; all current
2112 // implementations use an FBO internally in place of the default
2114 if (!m_framebufferBinding || !m_framebufferBinding->object()) {
2115 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "framebufferTexture2D", "no framebuffer bound");
2118 Platform3DObject textureObject = objectOrZero(texture);
2119 switch (attachment) {
2120 case GraphicsContext3D::DEPTH_STENCIL_ATTACHMENT:
2121 m_context->framebufferTexture2D(target, GraphicsContext3D::DEPTH_ATTACHMENT, textarget, textureObject, level);
2122 m_context->framebufferTexture2D(target, GraphicsContext3D::STENCIL_ATTACHMENT, textarget, textureObject, level);
2124 case GraphicsContext3D::DEPTH_ATTACHMENT:
2125 m_context->framebufferTexture2D(target, attachment, textarget, textureObject, level);
2127 case GraphicsContext3D::STENCIL_ATTACHMENT:
2128 m_context->framebufferTexture2D(target, attachment, textarget, textureObject, level);
2131 m_context->framebufferTexture2D(target, attachment, textarget, textureObject, level);
2133 m_framebufferBinding->setAttachmentForBoundFramebuffer(attachment, textarget, texture, level);
2135 cleanupAfterGraphicsCall(false);
2138 void WebGLRenderingContext::frontFace(GC3Denum mode)
2140 if (isContextLost())
2142 m_context->frontFace(mode);
2143 cleanupAfterGraphicsCall(false);
2146 void WebGLRenderingContext::generateMipmap(GC3Denum target)
2148 if (isContextLost())
2150 WebGLTexture* tex = validateTextureBinding("generateMipmap", target, false);
2153 if (!tex->canGenerateMipmaps()) {
2154 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "generateMipmap", "level 0 not power of 2 or not all the same size");
2157 if (!validateSettableTexFormat("generateMipmap", tex->getInternalFormat(target, 0)))
2160 // generateMipmap won't work properly if minFilter is not NEAREST_MIPMAP_LINEAR
2161 // on Mac. Remove the hack once this driver bug is fixed.
2163 bool needToResetMinFilter = false;
2164 if (tex->getMinFilter() != GraphicsContext3D::NEAREST_MIPMAP_LINEAR) {
2165 m_context->texParameteri(target, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::NEAREST_MIPMAP_LINEAR);
2166 needToResetMinFilter = true;
2169 m_context->generateMipmap(target);
2171 if (needToResetMinFilter)
2172 m_context->texParameteri(target, GraphicsContext3D::TEXTURE_MIN_FILTER, tex->getMinFilter());
2174 tex->generateMipmapLevelInfo();
2175 cleanupAfterGraphicsCall(false);
2178 PassRefPtr<WebGLActiveInfo> WebGLRenderingContext::getActiveAttrib(WebGLProgram* program, GC3Duint index, ExceptionCode& ec)
2181 if (isContextLost() || !validateWebGLObject("getActiveAttrib", program))
2184 if (!m_context->getActiveAttrib(objectOrZero(program), index, info))
2186 return WebGLActiveInfo::create(info.name, info.type, info.size);
2189 PassRefPtr<WebGLActiveInfo> WebGLRenderingContext::getActiveUniform(WebGLProgram* program, GC3Duint index, ExceptionCode& ec)
2192 if (isContextLost() || !validateWebGLObject("getActiveUniform", program))
2195 if (!m_context->getActiveUniform(objectOrZero(program), index, info))
2197 if (!isGLES2Compliant())
2198 if (info.size > 1 && !info.name.endsWith("[0]"))
2199 info.name.append("[0]");
2200 return WebGLActiveInfo::create(info.name, info.type, info.size);
2203 bool WebGLRenderingContext::getAttachedShaders(WebGLProgram* program, Vector<RefPtr<WebGLShader> >& shaderObjects, ExceptionCode& ec)
2206 shaderObjects.clear();
2207 if (isContextLost() || !validateWebGLObject("getAttachedShaders", program))
2210 const GC3Denum shaderType[] = {
2211 GraphicsContext3D::VERTEX_SHADER,
2212 GraphicsContext3D::FRAGMENT_SHADER
2214 for (unsigned i = 0; i < sizeof(shaderType) / sizeof(GC3Denum); ++i) {
2215 WebGLShader* shader = program->getAttachedShader(shaderType[i]);
2217 shaderObjects.append(shader);
2222 GC3Dint WebGLRenderingContext::getAttribLocation(WebGLProgram* program, const String& name)
2224 if (isContextLost() || !validateWebGLObject("getAttribLocation", program))
2226 if (!validateLocationLength("getAttribLocation", name))
2228 if (!validateString("getAttribLocation", name))
2230 if (isPrefixReserved(name))
2232 if (!program->getLinkStatus()) {
2233 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "getAttribLocation", "program not linked");
2236 return m_context->getAttribLocation(objectOrZero(program), name);
2239 WebGLGetInfo WebGLRenderingContext::getBufferParameter(GC3Denum target, GC3Denum pname, ExceptionCode& ec)
2242 if (isContextLost())
2243 return WebGLGetInfo();
2244 if (target != GraphicsContext3D::ARRAY_BUFFER && target != GraphicsContext3D::ELEMENT_ARRAY_BUFFER) {
2245 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getBufferParameter", "invalid target");
2246 return WebGLGetInfo();
2249 if (pname != GraphicsContext3D::BUFFER_SIZE && pname != GraphicsContext3D::BUFFER_USAGE) {
2250 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getBufferParameter", "invalid parameter name");
2251 return WebGLGetInfo();
2254 WebGLStateRestorer(this, false);
2256 m_context->getBufferParameteriv(target, pname, &value);
2257 if (pname == GraphicsContext3D::BUFFER_SIZE)
2258 return WebGLGetInfo(value);
2259 return WebGLGetInfo(static_cast<unsigned int>(value));
2262 PassRefPtr<WebGLContextAttributes> WebGLRenderingContext::getContextAttributes()
2264 if (isContextLost())
2266 // We always need to return a new WebGLContextAttributes object to
2267 // prevent the user from mutating any cached version.
2269 // Also, we need to enforce requested values of "false" for depth
2270 // and stencil, regardless of the properties of the underlying
2271 // GraphicsContext3D.
2272 RefPtr<WebGLContextAttributes> attributes = WebGLContextAttributes::create(m_context->getContextAttributes());
2273 if (!m_attributes.depth)
2274 attributes->setDepth(false);
2275 if (!m_attributes.stencil)
2276 attributes->setStencil(false);
2277 return attributes.release();
2280 GC3Denum WebGLRenderingContext::getError()
2282 return m_context->getError();
2285 WebGLExtension* WebGLRenderingContext::getExtension(const String& name)
2287 if (isContextLost())
2290 if (equalIgnoringCase(name, "WEBKIT_EXT_texture_filter_anisotropic")
2291 && m_context->getExtensions()->supports("GL_EXT_texture_filter_anisotropic")) {
2292 if (!m_extTextureFilterAnisotropic) {
2293 m_context->getExtensions()->ensureEnabled("GL_EXT_texture_filter_anisotropic");
2294 m_extTextureFilterAnisotropic = EXTTextureFilterAnisotropic::create(this);
2296 return m_extTextureFilterAnisotropic.get();
2298 if (equalIgnoringCase(name, "OES_standard_derivatives")
2299 && m_context->getExtensions()->supports("GL_OES_standard_derivatives")) {
2300 if (!m_oesStandardDerivatives) {
2301 m_context->getExtensions()->ensureEnabled("GL_OES_standard_derivatives");
2302 m_oesStandardDerivatives = OESStandardDerivatives::create(this);
2304 return m_oesStandardDerivatives.get();
2306 if (equalIgnoringCase(name, "OES_texture_float")
2307 && m_context->getExtensions()->supports("GL_OES_texture_float")) {
2308 if (!m_oesTextureFloat) {
2309 m_context->getExtensions()->ensureEnabled("GL_OES_texture_float");
2310 m_oesTextureFloat = OESTextureFloat::create(this);
2312 return m_oesTextureFloat.get();
2314 if (equalIgnoringCase(name, "OES_vertex_array_object")
2315 && m_context->getExtensions()->supports("GL_OES_vertex_array_object")) {
2316 if (!m_oesVertexArrayObject) {
2317 m_context->getExtensions()->ensureEnabled("GL_OES_vertex_array_object");
2318 m_oesVertexArrayObject = OESVertexArrayObject::create(this);
2320 return m_oesVertexArrayObject.get();
2322 if (equalIgnoringCase(name, "WEBKIT_WEBGL_lose_context")
2323 // FIXME: remove this after a certain grace period.
2324 || equalIgnoringCase(name, "WEBKIT_lose_context")) {
2325 if (!m_webglLoseContext)
2326 m_webglLoseContext = WebGLLoseContext::create(this);
2327 return m_webglLoseContext.get();
2329 if (equalIgnoringCase(name, "WEBKIT_WEBGL_compressed_texture_s3tc")) {
2330 // Use WEBKIT_ prefix until extension is official.
2331 if (!m_webglCompressedTextureS3TC)
2332 m_webglCompressedTextureS3TC = WebGLCompressedTextureS3TC::create(this);
2333 return m_webglCompressedTextureS3TC.get();
2335 if (equalIgnoringCase(name, "WEBKIT_WEBGL_depth_texture")
2336 && WebGLDepthTexture::supported(graphicsContext3D())) {
2337 if (!m_webglDepthTexture) {
2338 m_context->getExtensions()->ensureEnabled("GL_CHROMIUM_depth_texture");
2339 m_webglDepthTexture = WebGLDepthTexture::create(this);
2341 return m_webglDepthTexture.get();
2343 if (allowPrivilegedExtensions()) {
2344 if (equalIgnoringCase(name, "WEBGL_debug_renderer_info")) {
2345 if (!m_webglDebugRendererInfo)
2346 m_webglDebugRendererInfo = WebGLDebugRendererInfo::create(this);
2347 return m_webglDebugRendererInfo.get();
2349 if (equalIgnoringCase(name, "WEBGL_debug_shaders")
2350 && m_context->getExtensions()->supports("GL_ANGLE_translated_shader_source")) {
2351 if (!m_webglDebugShaders)
2352 m_webglDebugShaders = WebGLDebugShaders::create(this);
2353 return m_webglDebugShaders.get();
2360 WebGLGetInfo WebGLRenderingContext::getFramebufferAttachmentParameter(GC3Denum target, GC3Denum attachment, GC3Denum pname, ExceptionCode& ec)
2363 if (isContextLost() || !validateFramebufferFuncParameters("getFramebufferAttachmentParameter", target, attachment))
2364 return WebGLGetInfo();
2366 if (!m_framebufferBinding || !m_framebufferBinding->object()) {
2367 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "getFramebufferAttachmentParameter", "no framebuffer bound");
2368 return WebGLGetInfo();
2371 WebGLSharedObject* object = m_framebufferBinding->getAttachmentObject(attachment);
2373 if (pname == GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE)
2374 return WebGLGetInfo(GraphicsContext3D::NONE);
2375 // OpenGL ES 2.0 specifies INVALID_ENUM in this case, while desktop GL
2376 // specifies INVALID_OPERATION.
2377 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getFramebufferAttachmentParameter", "invalid parameter name");
2378 return WebGLGetInfo();
2381 ASSERT(object->isTexture() || object->isRenderbuffer());
2382 if (object->isTexture()) {
2384 case GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
2385 return WebGLGetInfo(GraphicsContext3D::TEXTURE);
2386 case GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
2387 return WebGLGetInfo(PassRefPtr<WebGLTexture>(reinterpret_cast<WebGLTexture*>(object)));
2388 case GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
2389 case GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
2391 WebGLStateRestorer(this, false);
2393 m_context->getFramebufferAttachmentParameteriv(target, attachment, pname, &value);
2394 return WebGLGetInfo(value);
2397 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getFramebufferAttachmentParameter", "invalid parameter name for texture attachment");
2398 return WebGLGetInfo();
2402 case GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
2403 return WebGLGetInfo(GraphicsContext3D::RENDERBUFFER);
2404 case GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
2405 return WebGLGetInfo(PassRefPtr<WebGLRenderbuffer>(reinterpret_cast<WebGLRenderbuffer*>(object)));
2407 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getFramebufferAttachmentParameter", "invalid parameter name for renderbuffer attachment");
2408 return WebGLGetInfo();
2413 WebGLGetInfo WebGLRenderingContext::getParameter(GC3Denum pname, ExceptionCode& ec)
2416 if (isContextLost())
2417 return WebGLGetInfo();
2418 const int intZero = 0;
2419 WebGLStateRestorer(this, false);
2421 case GraphicsContext3D::ACTIVE_TEXTURE:
2422 return getUnsignedIntParameter(pname);
2423 case GraphicsContext3D::ALIASED_LINE_WIDTH_RANGE:
2424 return getWebGLFloatArrayParameter(pname);
2425 case GraphicsContext3D::ALIASED_POINT_SIZE_RANGE:
2426 return getWebGLFloatArrayParameter(pname);
2427 case GraphicsContext3D::ALPHA_BITS:
2428 return getIntParameter(pname);
2429 case GraphicsContext3D::ARRAY_BUFFER_BINDING:
2430 return WebGLGetInfo(PassRefPtr<WebGLBuffer>(m_boundArrayBuffer));
2431 case GraphicsContext3D::BLEND:
2432 return getBooleanParameter(pname);
2433 case GraphicsContext3D::BLEND_COLOR:
2434 return getWebGLFloatArrayParameter(pname);
2435 case GraphicsContext3D::BLEND_DST_ALPHA:
2436 return getUnsignedIntParameter(pname);
2437 case GraphicsContext3D::BLEND_DST_RGB:
2438 return getUnsignedIntParameter(pname);
2439 case GraphicsContext3D::BLEND_EQUATION_ALPHA:
2440 return getUnsignedIntParameter(pname);
2441 case GraphicsContext3D::BLEND_EQUATION_RGB:
2442 return getUnsignedIntParameter(pname);
2443 case GraphicsContext3D::BLEND_SRC_ALPHA:
2444 return getUnsignedIntParameter(pname);
2445 case GraphicsContext3D::BLEND_SRC_RGB:
2446 return getUnsignedIntParameter(pname);
2447 case GraphicsContext3D::BLUE_BITS:
2448 return getIntParameter(pname);
2449 case GraphicsContext3D::COLOR_CLEAR_VALUE:
2450 return getWebGLFloatArrayParameter(pname);
2451 case GraphicsContext3D::COLOR_WRITEMASK:
2452 return getBooleanArrayParameter(pname);
2453 case GraphicsContext3D::COMPRESSED_TEXTURE_FORMATS:
2454 return WebGLGetInfo(Uint32Array::create(m_compressedTextureFormats.data(), m_compressedTextureFormats.size()));
2455 case GraphicsContext3D::CULL_FACE:
2456 return getBooleanParameter(pname);
2457 case GraphicsContext3D::CULL_FACE_MODE:
2458 return getUnsignedIntParameter(pname);
2459 case GraphicsContext3D::CURRENT_PROGRAM:
2460 return WebGLGetInfo(PassRefPtr<WebGLProgram>(m_currentProgram));
2461 case GraphicsContext3D::DEPTH_BITS:
2462 if (!m_framebufferBinding && !m_attributes.depth)
2463 return WebGLGetInfo(intZero);
2464 return getIntParameter(pname);
2465 case GraphicsContext3D::DEPTH_CLEAR_VALUE:
2466 return getFloatParameter(pname);
2467 case GraphicsContext3D::DEPTH_FUNC:
2468 return getUnsignedIntParameter(pname);
2469 case GraphicsContext3D::DEPTH_RANGE:
2470 return getWebGLFloatArrayParameter(pname);
2471 case GraphicsContext3D::DEPTH_TEST:
2472 return getBooleanParameter(pname);
2473 case GraphicsContext3D::DEPTH_WRITEMASK:
2474 return getBooleanParameter(pname);
2475 case GraphicsContext3D::DITHER:
2476 return getBooleanParameter(pname);
2477 case GraphicsContext3D::ELEMENT_ARRAY_BUFFER_BINDING:
2478 return WebGLGetInfo(PassRefPtr<WebGLBuffer>(m_boundVertexArrayObject->getElementArrayBuffer()));
2479 case GraphicsContext3D::FRAMEBUFFER_BINDING:
2480 return WebGLGetInfo(PassRefPtr<WebGLFramebuffer>(m_framebufferBinding));
2481 case GraphicsContext3D::FRONT_FACE:
2482 return getUnsignedIntParameter(pname);
2483 case GraphicsContext3D::GENERATE_MIPMAP_HINT:
2484 return getUnsignedIntParameter(pname);
2485 case GraphicsContext3D::GREEN_BITS:
2486 return getIntParameter(pname);
2487 case GraphicsContext3D::LINE_WIDTH:
2488 return getFloatParameter(pname);
2489 case GraphicsContext3D::MAX_COMBINED_TEXTURE_IMAGE_UNITS:
2490 return getIntParameter(pname);
2491 case GraphicsContext3D::MAX_CUBE_MAP_TEXTURE_SIZE:
2492 return getIntParameter(pname);
2493 case GraphicsContext3D::MAX_FRAGMENT_UNIFORM_VECTORS:
2494 return getIntParameter(pname);
2495 case GraphicsContext3D::MAX_RENDERBUFFER_SIZE:
2496 return getIntParameter(pname);
2497 case GraphicsContext3D::MAX_TEXTURE_IMAGE_UNITS:
2498 return getIntParameter(pname);
2499 case GraphicsContext3D::MAX_TEXTURE_SIZE:
2500 return getIntParameter(pname);
2501 case GraphicsContext3D::MAX_VARYING_VECTORS:
2502 return getIntParameter(pname);
2503 case GraphicsContext3D::MAX_VERTEX_ATTRIBS:
2504 return getIntParameter(pname);
2505 case GraphicsContext3D::MAX_VERTEX_TEXTURE_IMAGE_UNITS:
2506 return getIntParameter(pname);
2507 case GraphicsContext3D::MAX_VERTEX_UNIFORM_VECTORS:
2508 return getIntParameter(pname);
2509 case GraphicsContext3D::MAX_VIEWPORT_DIMS:
2510 return getWebGLIntArrayParameter(pname);
2511 case GraphicsContext3D::NUM_SHADER_BINARY_FORMATS:
2512 // FIXME: should we always return 0 for this?
2513 return getIntParameter(pname);
2514 case GraphicsContext3D::PACK_ALIGNMENT:
2515 return getIntParameter(pname);
2516 case GraphicsContext3D::POLYGON_OFFSET_FACTOR:
2517 return getFloatParameter(pname);
2518 case GraphicsContext3D::POLYGON_OFFSET_FILL:
2519 return getBooleanParameter(pname);
2520 case GraphicsContext3D::POLYGON_OFFSET_UNITS:
2521 return getFloatParameter(pname);
2522 case GraphicsContext3D::RED_BITS:
2523 return getIntParameter(pname);
2524 case GraphicsContext3D::RENDERBUFFER_BINDING:
2525 return WebGLGetInfo(PassRefPtr<WebGLRenderbuffer>(m_renderbufferBinding));
2526 case GraphicsContext3D::RENDERER:
2527 return WebGLGetInfo(String("WebKit WebGL"));
2528 case GraphicsContext3D::SAMPLE_BUFFERS:
2529 return getIntParameter(pname);
2530 case GraphicsContext3D::SAMPLE_COVERAGE_INVERT:
2531 return getBooleanParameter(pname);
2532 case GraphicsContext3D::SAMPLE_COVERAGE_VALUE:
2533 return getFloatParameter(pname);
2534 case GraphicsContext3D::SAMPLES:
2535 return getIntParameter(pname);
2536 case GraphicsContext3D::SCISSOR_BOX:
2537 return getWebGLIntArrayParameter(pname);
2538 case GraphicsContext3D::SCISSOR_TEST:
2539 return getBooleanParameter(pname);
2540 case GraphicsContext3D::SHADING_LANGUAGE_VERSION:
2541 return WebGLGetInfo("WebGL GLSL ES 1.0 (" + m_context->getString(GraphicsContext3D::SHADING_LANGUAGE_VERSION) + ")");
2542 case GraphicsContext3D::STENCIL_BACK_FAIL:
2543 return getUnsignedIntParameter(pname);
2544 case GraphicsContext3D::STENCIL_BACK_FUNC:
2545 return getUnsignedIntParameter(pname);
2546 case GraphicsContext3D::STENCIL_BACK_PASS_DEPTH_FAIL:
2547 return getUnsignedIntParameter(pname);
2548 case GraphicsContext3D::STENCIL_BACK_PASS_DEPTH_PASS:
2549 return getUnsignedIntParameter(pname);
2550 case GraphicsContext3D::STENCIL_BACK_REF:
2551 return getIntParameter(pname);
2552 case GraphicsContext3D::STENCIL_BACK_VALUE_MASK:
2553 return getUnsignedIntParameter(pname);
2554 case GraphicsContext3D::STENCIL_BACK_WRITEMASK:
2555 return getUnsignedIntParameter(pname);
2556 case GraphicsContext3D::STENCIL_BITS:
2557 if (!m_framebufferBinding && !m_attributes.stencil)
2558 return WebGLGetInfo(intZero);
2559 return getIntParameter(pname);
2560 case GraphicsContext3D::STENCIL_CLEAR_VALUE:
2561 return getIntParameter(pname);
2562 case GraphicsContext3D::STENCIL_FAIL:
2563 return getUnsignedIntParameter(pname);
2564 case GraphicsContext3D::STENCIL_FUNC:
2565 return getUnsignedIntParameter(pname);
2566 case GraphicsContext3D::STENCIL_PASS_DEPTH_FAIL:
2567 return getUnsignedIntParameter(pname);
2568 case GraphicsContext3D::STENCIL_PASS_DEPTH_PASS:
2569 return getUnsignedIntParameter(pname);
2570 case GraphicsContext3D::STENCIL_REF:
2571 return getIntParameter(pname);
2572 case GraphicsContext3D::STENCIL_TEST:
2573 return getBooleanParameter(pname);
2574 case GraphicsContext3D::STENCIL_VALUE_MASK:
2575 return getUnsignedIntParameter(pname);
2576 case GraphicsContext3D::STENCIL_WRITEMASK:
2577 return getUnsignedIntParameter(pname);
2578 case GraphicsContext3D::SUBPIXEL_BITS:
2579 return getIntParameter(pname);
2580 case GraphicsContext3D::TEXTURE_BINDING_2D:
2581 return WebGLGetInfo(PassRefPtr<WebGLTexture>(m_textureUnits[m_activeTextureUnit].m_texture2DBinding));
2582 case GraphicsContext3D::TEXTURE_BINDING_CUBE_MAP:
2583 return WebGLGetInfo(PassRefPtr<WebGLTexture>(m_textureUnits[m_activeTextureUnit].m_textureCubeMapBinding));
2584 case GraphicsContext3D::UNPACK_ALIGNMENT:
2585 return getIntParameter(pname);
2586 case GraphicsContext3D::UNPACK_FLIP_Y_WEBGL:
2587 return WebGLGetInfo(m_unpackFlipY);
2588 case GraphicsContext3D::UNPACK_PREMULTIPLY_ALPHA_WEBGL:
2589 return WebGLGetInfo(m_unpackPremultiplyAlpha);
2590 case GraphicsContext3D::UNPACK_COLORSPACE_CONVERSION_WEBGL:
2591 return WebGLGetInfo(m_unpackColorspaceConversion);
2592 case GraphicsContext3D::VENDOR:
2593 return WebGLGetInfo(String("WebKit"));
2594 case GraphicsContext3D::VERSION:
2595 return WebGLGetInfo("WebGL 1.0 (" + m_context->getString(GraphicsContext3D::VERSION) + ")");
2596 case GraphicsContext3D::VIEWPORT:
2597 return getWebGLIntArrayParameter(pname);
2598 case Extensions3D::FRAGMENT_SHADER_DERIVATIVE_HINT_OES: // OES_standard_derivatives
2599 if (m_oesStandardDerivatives)
2600 return getUnsignedIntParameter(Extensions3D::FRAGMENT_SHADER_DERIVATIVE_HINT_OES);
2601 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getParameter", "invalid parameter name, OES_standard_derivatives not enabled");
2602 return WebGLGetInfo();
2603 case WebGLDebugRendererInfo::UNMASKED_RENDERER_WEBGL:
2604 if (m_webglDebugRendererInfo)
2605 return WebGLGetInfo(m_context->getString(GraphicsContext3D::RENDERER));
2606 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getParameter", "invalid parameter name, WEBGL_debug_renderer_info not enabled");
2607 return WebGLGetInfo();
2608 case WebGLDebugRendererInfo::UNMASKED_VENDOR_WEBGL:
2609 if (m_webglDebugRendererInfo)
2610 return WebGLGetInfo(m_context->getString(GraphicsContext3D::VENDOR));
2611 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getParameter", "invalid parameter name, WEBGL_debug_renderer_info not enabled");
2612 return WebGLGetInfo();
2613 case Extensions3D::VERTEX_ARRAY_BINDING_OES: // OES_vertex_array_object
2614 if (m_oesVertexArrayObject) {
2615 if (!m_boundVertexArrayObject->isDefaultObject())
2616 return WebGLGetInfo(PassRefPtr<WebGLVertexArrayObjectOES>(m_boundVertexArrayObject));
2617 return WebGLGetInfo();
2619 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getParameter", "invalid parameter name, OES_vertex_array_object not enabled");
2620 return WebGLGetInfo();
2621 case Extensions3D::MAX_TEXTURE_MAX_ANISOTROPY_EXT: // EXT_texture_filter_anisotropic
2622 if (m_extTextureFilterAnisotropic)
2623 return getUnsignedIntParameter(Extensions3D::MAX_TEXTURE_MAX_ANISOTROPY_EXT);
2624 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getParameter", "invalid parameter name, EXT_texture_filter_anisotropic not enabled");
2625 return WebGLGetInfo();
2627 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getParameter", "invalid parameter name");
2628 return WebGLGetInfo();
2632 WebGLGetInfo WebGLRenderingContext::getProgramParameter(WebGLProgram* program, GC3Denum pname, ExceptionCode& ec)
2635 if (isContextLost() || !validateWebGLObject("getProgramParameter", program))
2636 return WebGLGetInfo();
2638 WebGLStateRestorer(this, false);
2641 case GraphicsContext3D::DELETE_STATUS:
2642 return WebGLGetInfo(program->isDeleted());
2643 case GraphicsContext3D::VALIDATE_STATUS:
2644 m_context->getProgramiv(objectOrZero(program), pname, &value);
2645 return WebGLGetInfo(static_cast<bool>(value));
2646 case GraphicsContext3D::LINK_STATUS:
2647 return WebGLGetInfo(program->getLinkStatus());
2648 case GraphicsContext3D::ATTACHED_SHADERS:
2649 case GraphicsContext3D::ACTIVE_ATTRIBUTES:
2650 case GraphicsContext3D::ACTIVE_UNIFORMS:
2651 m_context->getProgramiv(objectOrZero(program), pname, &value);
2652 return WebGLGetInfo(value);
2654 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getProgramParameter", "invalid parameter name");
2655 return WebGLGetInfo();
2659 String WebGLRenderingContext::getProgramInfoLog(WebGLProgram* program, ExceptionCode& ec)
2662 if (isContextLost())
2664 if (!validateWebGLObject("getProgramInfoLog", program))
2666 WebGLStateRestorer(this, false);
2667 return ensureNotNull(m_context->getProgramInfoLog(objectOrZero(program)));
2670 WebGLGetInfo WebGLRenderingContext::getRenderbufferParameter(GC3Denum target, GC3Denum pname, ExceptionCode& ec)
2673 if (isContextLost())
2674 return WebGLGetInfo();
2675 if (target != GraphicsContext3D::RENDERBUFFER) {
2676 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getRenderbufferParameter", "invalid target");
2677 return WebGLGetInfo();
2679 if (!m_renderbufferBinding || !m_renderbufferBinding->object()) {
2680 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "getRenderbufferParameter", "no renderbuffer bound");
2681 return WebGLGetInfo();
2684 if (m_renderbufferBinding->getInternalFormat() == GraphicsContext3D::DEPTH_STENCIL
2685 && !m_renderbufferBinding->isValid()) {
2686 ASSERT(!isDepthStencilSupported());
2689 case GraphicsContext3D::RENDERBUFFER_WIDTH:
2690 value = m_renderbufferBinding->getWidth();
2692 case GraphicsContext3D::RENDERBUFFER_HEIGHT:
2693 value = m_renderbufferBinding->getHeight();
2695 case GraphicsContext3D::RENDERBUFFER_RED_SIZE:
2696 case GraphicsContext3D::RENDERBUFFER_GREEN_SIZE:
2697 case GraphicsContext3D::RENDERBUFFER_BLUE_SIZE:
2698 case GraphicsContext3D::RENDERBUFFER_ALPHA_SIZE:
2701 case GraphicsContext3D::RENDERBUFFER_DEPTH_SIZE:
2704 case GraphicsContext3D::RENDERBUFFER_STENCIL_SIZE:
2707 case GraphicsContext3D::RENDERBUFFER_INTERNAL_FORMAT:
2708 return WebGLGetInfo(m_renderbufferBinding->getInternalFormat());
2710 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getRenderbufferParameter", "invalid parameter name");
2711 return WebGLGetInfo();
2713 return WebGLGetInfo(value);
2716 WebGLStateRestorer(this, false);
2719 case GraphicsContext3D::RENDERBUFFER_WIDTH:
2720 case GraphicsContext3D::RENDERBUFFER_HEIGHT:
2721 case GraphicsContext3D::RENDERBUFFER_RED_SIZE:
2722 case GraphicsContext3D::RENDERBUFFER_GREEN_SIZE:
2723 case GraphicsContext3D::RENDERBUFFER_BLUE_SIZE:
2724 case GraphicsContext3D::RENDERBUFFER_ALPHA_SIZE:
2725 case GraphicsContext3D::RENDERBUFFER_DEPTH_SIZE:
2726 case GraphicsContext3D::RENDERBUFFER_STENCIL_SIZE:
2727 m_context->getRenderbufferParameteriv(target, pname, &value);
2728 return WebGLGetInfo(value);
2729 case GraphicsContext3D::RENDERBUFFER_INTERNAL_FORMAT:
2730 return WebGLGetInfo(m_renderbufferBinding->getInternalFormat());
2732 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getRenderbufferParameter", "invalid parameter name");
2733 return WebGLGetInfo();
2737 WebGLGetInfo WebGLRenderingContext::getShaderParameter(WebGLShader* shader, GC3Denum pname, ExceptionCode& ec)
2740 if (isContextLost() || !validateWebGLObject("getShaderParameter", shader))
2741 return WebGLGetInfo();
2742 WebGLStateRestorer(this, false);
2745 case GraphicsContext3D::DELETE_STATUS:
2746 return WebGLGetInfo(shader->isDeleted());
2747 case GraphicsContext3D::COMPILE_STATUS:
2748 m_context->getShaderiv(objectOrZero(shader), pname, &value);
2749 return WebGLGetInfo(static_cast<bool>(value));
2750 case GraphicsContext3D::SHADER_TYPE:
2751 m_context->getShaderiv(objectOrZero(shader), pname, &value);
2752 return WebGLGetInfo(static_cast<unsigned int>(value));
2754 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getShaderParameter", "invalid parameter name");
2755 return WebGLGetInfo();
2759 String WebGLRenderingContext::getShaderInfoLog(WebGLShader* shader, ExceptionCode& ec)
2762 if (isContextLost())
2764 if (!validateWebGLObject("getShaderInfoLog", shader))
2766 WebGLStateRestorer(this, false);
2767 return ensureNotNull(m_context->getShaderInfoLog(objectOrZero(shader)));
2770 PassRefPtr<WebGLShaderPrecisionFormat> WebGLRenderingContext::getShaderPrecisionFormat(GC3Denum shaderType, GC3Denum precisionType, ExceptionCode& ec)
2773 if (isContextLost())
2775 switch (shaderType) {
2776 case GraphicsContext3D::VERTEX_SHADER:
2777 case GraphicsContext3D::FRAGMENT_SHADER:
2780 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getShaderPrecisionFormat", "invalid shader type");
2783 switch (precisionType) {
2784 case GraphicsContext3D::LOW_FLOAT:
2785 case GraphicsContext3D::MEDIUM_FLOAT:
2786 case GraphicsContext3D::HIGH_FLOAT:
2787 case GraphicsContext3D::LOW_INT:
2788 case GraphicsContext3D::MEDIUM_INT:
2789 case GraphicsContext3D::HIGH_INT:
2792 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getShaderPrecisionFormat", "invalid precision type");
2796 GC3Dint range[2] = {0, 0};
2797 GC3Dint precision = 0;
2798 #if !ENABLE(TIZEN_DAILY_UPVERSIONING)
2799 // FIXME: getShaderPrecisionFormat() should be implemented.
2800 m_context->getShaderPrecisionFormat(shaderType, precisionType, range, &precision);
2802 return WebGLShaderPrecisionFormat::create(range[0], range[1], precision);
2805 String WebGLRenderingContext::getShaderSource(WebGLShader* shader, ExceptionCode& ec)
2808 if (isContextLost())
2810 if (!validateWebGLObject("getShaderSource", shader))
2812 return ensureNotNull(shader->getSource());
2815 Vector<String> WebGLRenderingContext::getSupportedExtensions()
2817 Vector<String> result;
2818 if (m_context->getExtensions()->supports("GL_OES_texture_float"))
2819 result.append("OES_texture_float");
2820 if (m_context->getExtensions()->supports("GL_OES_standard_derivatives"))
2821 result.append("OES_standard_derivatives");
2822 if (m_context->getExtensions()->supports("GL_EXT_texture_filter_anisotropic"))
2823 result.append("WEBKIT_EXT_texture_filter_anisotropic");
2824 if (m_context->getExtensions()->supports("GL_OES_vertex_array_object"))
2825 result.append("OES_vertex_array_object");
2826 result.append("WEBKIT_WEBGL_lose_context");
2827 if (WebGLCompressedTextureS3TC::supported(this))
2828 result.append("WEBKIT_WEBGL_compressed_texture_s3tc");
2829 if (WebGLDepthTexture::supported(graphicsContext3D()))
2830 result.append("WEBKIT_WEBGL_depth_texture");
2832 if (allowPrivilegedExtensions()) {
2833 if (m_context->getExtensions()->supports("GL_ANGLE_translated_shader_source"))
2834 result.append("WEBGL_debug_shaders");
2835 result.append("WEBGL_debug_renderer_info");
2841 WebGLGetInfo WebGLRenderingContext::getTexParameter(GC3Denum target, GC3Denum pname, ExceptionCode& ec)
2844 if (isContextLost())
2845 return WebGLGetInfo();
2846 WebGLTexture* tex = validateTextureBinding("getTexParameter", target, false);
2848 return WebGLGetInfo();
2849 WebGLStateRestorer(this, false);
2852 case GraphicsContext3D::TEXTURE_MAG_FILTER:
2853 case GraphicsContext3D::TEXTURE_MIN_FILTER:
2854 case GraphicsContext3D::TEXTURE_WRAP_S:
2855 case GraphicsContext3D::TEXTURE_WRAP_T:
2856 m_context->getTexParameteriv(target, pname, &value);
2857 return WebGLGetInfo(static_cast<unsigned int>(value));
2858 case Extensions3D::TEXTURE_MAX_ANISOTROPY_EXT: // EXT_texture_filter_anisotropic
2859 if (m_extTextureFilterAnisotropic) {
2860 m_context->getTexParameteriv(target, pname, &value);
2861 return WebGLGetInfo(static_cast<unsigned int>(value));
2863 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getTexParameter", "invalid parameter name, EXT_texture_filter_anisotropic not enabled");
2864 return WebGLGetInfo();
2866 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getTexParameter", "invalid parameter name");
2867 return WebGLGetInfo();
2871 WebGLGetInfo WebGLRenderingContext::getUniform(WebGLProgram* program, const WebGLUniformLocation* uniformLocation, ExceptionCode& ec)
2874 if (isContextLost() || !validateWebGLObject("getUniform", program))
2875 return WebGLGetInfo();
2876 if (!uniformLocation || uniformLocation->program() != program) {
2877 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "getUniform", "no uniformlocation or not valid for this program");
2878 return WebGLGetInfo();
2880 GC3Dint location = uniformLocation->location();
2882 WebGLStateRestorer(this, false);
2883 // FIXME: make this more efficient using WebGLUniformLocation and caching types in it
2884 GC3Dint activeUniforms = 0;
2885 m_context->getProgramiv(objectOrZero(program), GraphicsContext3D::ACTIVE_UNIFORMS, &activeUniforms);
2886 for (GC3Dint i = 0; i < activeUniforms; i++) {
2888 if (!m_context->getActiveUniform(objectOrZero(program), i, info))
2889 return WebGLGetInfo();
2890 // Strip "[0]" from the name if it's an array.
2891 if (info.size > 1 && info.name.endsWith("[0]"))
2892 info.name = info.name.left(info.name.length() - 3);
2893 // If it's an array, we need to iterate through each element, appending "[index]" to the name.
2894 for (GC3Dint index = 0; index < info.size; ++index) {
2895 String name = info.name;
2896 if (info.size > 1 && index >= 1) {
2898 name.append(String::number(index));
2901 // Now need to look this up by name again to find its location
2902 GC3Dint loc = m_context->getUniformLocation(objectOrZero(program), name);
2903 if (loc == location) {
2904 // Found it. Use the type in the ActiveInfo to determine the return type.
2906 unsigned int length;
2907 switch (info.type) {
2908 case GraphicsContext3D::BOOL:
2909 baseType = GraphicsContext3D::BOOL;
2912 case GraphicsContext3D::BOOL_VEC2:
2913 baseType = GraphicsContext3D::BOOL;
2916 case GraphicsContext3D::BOOL_VEC3:
2917 baseType = GraphicsContext3D::BOOL;
2920 case GraphicsContext3D::BOOL_VEC4:
2921 baseType = GraphicsContext3D::BOOL;
2924 case GraphicsContext3D::INT:
2925 baseType = GraphicsContext3D::INT;
2928 case GraphicsContext3D::INT_VEC2:
2929 baseType = GraphicsContext3D::INT;
2932 case GraphicsContext3D::INT_VEC3:
2933 baseType = GraphicsContext3D::INT;
2936 case GraphicsContext3D::INT_VEC4:
2937 baseType = GraphicsContext3D::INT;
2940 case GraphicsContext3D::FLOAT:
2941 baseType = GraphicsContext3D::FLOAT;
2944 case GraphicsContext3D::FLOAT_VEC2:
2945 baseType = GraphicsContext3D::FLOAT;
2948 case GraphicsContext3D::FLOAT_VEC3:
2949 baseType = GraphicsContext3D::FLOAT;
2952 case GraphicsContext3D::FLOAT_VEC4:
2953 baseType = GraphicsContext3D::FLOAT;
2956 case GraphicsContext3D::FLOAT_MAT2:
2957 baseType = GraphicsContext3D::FLOAT;
2960 case GraphicsContext3D::FLOAT_MAT3:
2961 baseType = GraphicsContext3D::FLOAT;
2964 case GraphicsContext3D::FLOAT_MAT4:
2965 baseType = GraphicsContext3D::FLOAT;
2968 case GraphicsContext3D::SAMPLER_2D:
2969 case GraphicsContext3D::SAMPLER_CUBE:
2970 baseType = GraphicsContext3D::INT;
2974 // Can't handle this type
2975 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "getUniform", "unhandled type");
2976 return WebGLGetInfo();
2979 case GraphicsContext3D::FLOAT: {
2980 GC3Dfloat value[16] = {0};
2981 m_context->getUniformfv(objectOrZero(program), location, value);
2983 return WebGLGetInfo(value[0]);
2984 return WebGLGetInfo(Float32Array::create(value, length));
2986 case GraphicsContext3D::INT: {
2987 GC3Dint value[4] = {0};
2988 m_context->getUniformiv(objectOrZero(program), location, value);
2990 return WebGLGetInfo(value[0]);
2991 return WebGLGetInfo(Int32Array::create(value, length));
2993 case GraphicsContext3D::BOOL: {
2994 GC3Dint value[4] = {0};
2995 m_context->getUniformiv(objectOrZero(program), location, value);
2997 bool boolValue[16] = {0};
2998 for (unsigned j = 0; j < length; j++)
2999 boolValue[j] = static_cast<bool>(value[j]);
3000 return WebGLGetInfo(boolValue, length);
3002 return WebGLGetInfo(static_cast<bool>(value[0]));
3010 // If we get here, something went wrong in our unfortunately complex logic above
3011 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "getUniform", "unknown error");
3012 return WebGLGetInfo();
3015 PassRefPtr<WebGLUniformLocation> WebGLRenderingContext::getUniformLocation(WebGLProgram* program, const String& name, ExceptionCode& ec)
3018 if (isContextLost() || !validateWebGLObject("getUniformLocation", program))
3020 if (!validateLocationLength("getUniformLocation", name))
3022 if (!validateString("getUniformLocation", name))
3024 if (isPrefixReserved(name))
3026 if (!program->getLinkStatus()) {
3027 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "getUniformLocation", "program not linked");
3030 WebGLStateRestorer(this, false);
3031 GC3Dint uniformLocation = m_context->getUniformLocation(objectOrZero(program), name);
3032 if (uniformLocation == -1)
3034 return WebGLUniformLocation::create(program, uniformLocation);
3037 WebGLGetInfo WebGLRenderingContext::getVertexAttrib(GC3Duint index, GC3Denum pname, ExceptionCode& ec)
3040 if (isContextLost())
3041 return WebGLGetInfo();
3042 WebGLStateRestorer(this, false);
3043 if (index >= m_maxVertexAttribs) {
3044 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "getVertexAttrib", "index out of range");
3045 return WebGLGetInfo();
3047 const WebGLVertexArrayObjectOES::VertexAttribState& state = m_boundVertexArrayObject->getVertexAttribState(index);
3049 case GraphicsContext3D::VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
3050 if ((!isGLES2Compliant() && !index && m_boundVertexArrayObject->getVertexAttribState(0).bufferBinding == m_vertexAttrib0Buffer)
3051 || !state.bufferBinding
3052 || !state.bufferBinding->object())
3053 return WebGLGetInfo();
3054 return WebGLGetInfo(PassRefPtr<WebGLBuffer>(state.bufferBinding));
3055 case GraphicsContext3D::VERTEX_ATTRIB_ARRAY_ENABLED:
3056 return WebGLGetInfo(state.enabled);
3057 case GraphicsContext3D::VERTEX_ATTRIB_ARRAY_NORMALIZED:
3058 return WebGLGetInfo(state.normalized);
3059 case GraphicsContext3D::VERTEX_ATTRIB_ARRAY_SIZE:
3060 return WebGLGetInfo(state.size);
3061 case GraphicsContext3D::VERTEX_ATTRIB_ARRAY_STRIDE:
3062 return WebGLGetInfo(state.originalStride);
3063 case GraphicsContext3D::VERTEX_ATTRIB_ARRAY_TYPE:
3064 return WebGLGetInfo(state.type);
3065 case GraphicsContext3D::CURRENT_VERTEX_ATTRIB:
3066 return WebGLGetInfo(Float32Array::create(m_vertexAttribValue[index].value, 4));
3068 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getVertexAttrib", "invalid parameter name");
3069 return WebGLGetInfo();
3073 long long WebGLRenderingContext::getVertexAttribOffset(GC3Duint index, GC3Denum pname)
3075 if (isContextLost())
3077 GC3Dsizeiptr result = m_context->getVertexAttribOffset(index, pname);
3078 cleanupAfterGraphicsCall(false);
3079 return static_cast<long long>(result);
3082 void WebGLRenderingContext::hint(GC3Denum target, GC3Denum mode)
3084 if (isContextLost())
3086 bool isValid = false;
3088 case GraphicsContext3D::GENERATE_MIPMAP_HINT:
3091 case Extensions3D::FRAGMENT_SHADER_DERIVATIVE_HINT_OES: // OES_standard_derivatives
3092 if (m_oesStandardDerivatives)
3097 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "hint", "invalid target");
3100 m_context->hint(target, mode);
3101 cleanupAfterGraphicsCall(false);
3104 GC3Dboolean WebGLRenderingContext::isBuffer(WebGLBuffer* buffer)
3106 if (!buffer || isContextLost())
3109 if (!buffer->hasEverBeenBound())
3112 return m_context->isBuffer(buffer->object());
3115 bool WebGLRenderingContext::isContextLost()
3117 return m_contextLost;
3120 GC3Dboolean WebGLRenderingContext::isEnabled(GC3Denum cap)
3122 if (isContextLost() || !validateCapability("isEnabled", cap))
3124 if (cap == GraphicsContext3D::STENCIL_TEST)
3125 return m_stencilEnabled;
3126 return m_context->isEnabled(cap);
3129 GC3Dboolean WebGLRenderingContext::isFramebuffer(WebGLFramebuffer* framebuffer)
3131 if (!framebuffer || isContextLost())
3134 if (!framebuffer->hasEverBeenBound())
3137 return m_context->isFramebuffer(framebuffer->object());
3140 GC3Dboolean WebGLRenderingContext::isProgram(WebGLProgram* program)
3142 if (!program || isContextLost())
3145 return m_context->isProgram(program->object());
3148 GC3Dboolean WebGLRenderingContext::isRenderbuffer(WebGLRenderbuffer* renderbuffer)
3150 if (!renderbuffer || isContextLost())
3153 if (!renderbuffer->hasEverBeenBound())
3156 return m_context->isRenderbuffer(renderbuffer->object());
3159 GC3Dboolean WebGLRenderingContext::isShader(WebGLShader* shader)
3161 if (!shader || isContextLost())
3164 return m_context->isShader(shader->object());
3167 GC3Dboolean WebGLRenderingContext::isTexture(WebGLTexture* texture)
3169 if (!texture || isContextLost())
3172 if (!texture->hasEverBeenBound())
3175 return m_context->isTexture(texture->object());
3178 void WebGLRenderingContext::lineWidth(GC3Dfloat width)
3180 if (isContextLost())
3182 m_context->lineWidth(width);
3183 cleanupAfterGraphicsCall(false);
3186 void WebGLRenderingContext::linkProgram(WebGLProgram* program, ExceptionCode& ec)
3189 if (isContextLost() || !validateWebGLObject("linkProgram", program))
3191 if (!isGLES2Compliant()) {
3192 if (!program->getAttachedShader(GraphicsContext3D::VERTEX_SHADER) || !program->getAttachedShader(GraphicsContext3D::FRAGMENT_SHADER)) {
3193 program->setLinkStatus(false);
3198 m_context->linkProgram(objectOrZero(program));
3199 program->increaseLinkCount();
3200 cleanupAfterGraphicsCall(false);
3203 void WebGLRenderingContext::pixelStorei(GC3Denum pname, GC3Dint param)
3205 if (isContextLost())
3208 case GraphicsContext3D::UNPACK_FLIP_Y_WEBGL:
3209 m_unpackFlipY = param;
3211 case GraphicsContext3D::UNPACK_PREMULTIPLY_ALPHA_WEBGL:
3212 m_unpackPremultiplyAlpha = param;
3214 case GraphicsContext3D::UNPACK_COLORSPACE_CONVERSION_WEBGL:
3215 if (param == GraphicsContext3D::BROWSER_DEFAULT_WEBGL || param == GraphicsContext3D::NONE)
3216 m_unpackColorspaceConversion = static_cast<GC3Denum>(param);
3218 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "pixelStorei", "invalid parameter for UNPACK_COLORSPACE_CONVERSION_WEBGL");
3222 case GraphicsContext3D::PACK_ALIGNMENT:
3223 case GraphicsContext3D::UNPACK_ALIGNMENT:
3224 if (param == 1 || param == 2 || param == 4 || param == 8) {
3225 if (pname == GraphicsContext3D::PACK_ALIGNMENT)
3226 m_packAlignment = param;
3227 else // GraphicsContext3D::UNPACK_ALIGNMENT:
3228 m_unpackAlignment = param;
3229 m_context->pixelStorei(pname, param);
3230 cleanupAfterGraphicsCall(false);
3232 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "pixelStorei", "invalid parameter for alignment");
3237 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "pixelStorei", "invalid parameter name");
3242 void WebGLRenderingContext::polygonOffset(GC3Dfloat factor, GC3Dfloat units)
3244 if (isContextLost())
3246 m_context->polygonOffset(factor, units);
3247 cleanupAfterGraphicsCall(false);
3250 void WebGLRenderingContext::readPixels(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height, GC3Denum format, GC3Denum type, ArrayBufferView* pixels, ExceptionCode&)
3252 if (isContextLost())
3254 // Due to WebGL's same-origin restrictions, it is not possible to
3255 // taint the origin using the WebGL API.
3256 ASSERT(canvas()->originClean());
3257 // Validate input parameters.
3259 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "readPixels", "no destination ArrayBufferView");
3263 case GraphicsContext3D::ALPHA:
3264 case GraphicsContext3D::RGB:
3265 case GraphicsContext3D::RGBA:
3268 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "readPixels", "invalid format");
3272 case GraphicsContext3D::UNSIGNED_BYTE:
3273 case GraphicsContext3D::UNSIGNED_SHORT_5_6_5:
3274 case GraphicsContext3D::UNSIGNED_SHORT_4_4_4_4:
3275 case GraphicsContext3D::UNSIGNED_SHORT_5_5_5_1:
3278 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "readPixels", "invalid type");
3281 if (format != GraphicsContext3D::RGBA || type != GraphicsContext3D::UNSIGNED_BYTE) {
3282 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "readPixels", "format not RGBA or type not UNSIGNED_BYTE");
3285 // Validate array type against pixel type.
3286 if (pixels->getType() != ArrayBufferView::TypeUint8) {
3287 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "readPixels", "ArrayBufferView not Uint8Array");
3290 const char* reason = "framebuffer incomplete";
3291 if (m_framebufferBinding && !m_framebufferBinding->onAccess(graphicsContext3D(), !isResourceSafe(), &reason)) {
3292 synthesizeGLError(GraphicsContext3D::INVALID_FRAMEBUFFER_OPERATION, "readPixels", reason);
3295 // Calculate array size, taking into consideration of PACK_ALIGNMENT.
3296 unsigned int totalBytesRequired;
3297 unsigned int padding;
3298 GC3Denum error = m_context->computeImageSizeInBytes(format, type, width, height, m_packAlignment, &totalBytesRequired, &padding);
3299 if (error != GraphicsContext3D::NO_ERROR) {
3300 synthesizeGLError(error, "readPixels", "invalid dimensions");
3303 if (pixels->byteLength() < totalBytesRequired) {
3304 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "readPixels", "ArrayBufferView not large enough for dimensions");
3307 clearIfComposited();
3308 void* data = pixels->baseAddress();
3311 ScopedDrawingBufferBinder binder(m_drawingBuffer.get(), m_framebufferBinding.get());
3312 m_context->readPixels(x, y, width, height, format, type, data);
3315 #if OS(DARWIN) || OS(QNX) || PLATFORM(EFL)
3316 // FIXME: remove this section when GL driver bug on Mac AND the GLES driver bug
3317 // on QC & Imagination QNX is fixed, i.e., when alpha is off, readPixels should
3318 // set alpha to 255 instead of 0.
3319 if (!m_framebufferBinding && !m_context->getContextAttributes().alpha) {
3320 unsigned char* pixels = reinterpret_cast<unsigned char*>(data);
3321 for (GC3Dsizei iy = 0; iy < height; ++iy) {
3322 for (GC3Dsizei ix = 0; ix < width; ++ix) {
3330 cleanupAfterGraphicsCall(false);
3333 void WebGLRenderingContext::releaseShaderCompiler()
3335 if (isContextLost())
3337 m_context->releaseShaderCompiler();
3338 cleanupAfterGraphicsCall(false);
3341 void WebGLRenderingContext::renderbufferStorage(GC3Denum target, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height)
3343 if (isContextLost())
3345 if (target != GraphicsContext3D::RENDERBUFFER) {
3346 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "renderbufferStorage", "invalid target");
3349 if (!m_renderbufferBinding || !m_renderbufferBinding->object()) {
3350 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "renderbufferStorage", "no bound renderbuffer");
3353 if (!validateSize("renderbufferStorage", width, height))
3355 switch (internalformat) {
3356 case GraphicsContext3D::DEPTH_COMPONENT16:
3357 case GraphicsContext3D::RGBA4:
3358 case GraphicsContext3D::RGB5_A1:
3359 case GraphicsContext3D::RGB565:
3360 case GraphicsContext3D::STENCIL_INDEX8:
3361 m_context->renderbufferStorage(target, internalformat, width, height);
3362 m_renderbufferBinding->setInternalFormat(internalformat);
3363 m_renderbufferBinding->setIsValid(true);
3364 m_renderbufferBinding->setSize(width, height);
3365 cleanupAfterGraphicsCall(false);
3367 case GraphicsContext3D::DEPTH_STENCIL:
3368 if (isDepthStencilSupported()) {
3369 m_context->renderbufferStorage(target, Extensions3D::DEPTH24_STENCIL8, width, height);
3370 cleanupAfterGraphicsCall(false);
3372 m_renderbufferBinding->setSize(width, height);
3373 m_renderbufferBinding->setIsValid(isDepthStencilSupported());
3374 m_renderbufferBinding->setInternalFormat(internalformat);
3377 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "renderbufferStorage", "invalid internalformat");
3383 void WebGLRenderingContext::sampleCoverage(GC3Dfloat value, GC3Dboolean invert)
3385 if (isContextLost())
3387 m_context->sampleCoverage(value, invert);
3388 cleanupAfterGraphicsCall(false);
3391 void WebGLRenderingContext::scissor(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height)
3393 if (isContextLost())
3395 if (!validateSize("scissor", width, height))
3397 m_context->scissor(x, y, width, height);
3398 cleanupAfterGraphicsCall(false);
3401 void WebGLRenderingContext::shaderSource(WebGLShader* shader, const String& string, ExceptionCode& ec)
3404 if (isContextLost() || !validateWebGLObject("shaderSource", shader))
3406 String stringWithoutComments = StripComments(string).result();
3407 if (!validateString("shaderSource", stringWithoutComments))
3409 shader->setSource(string);
3410 m_context->shaderSource(objectOrZero(shader), stringWithoutComments);
3411 cleanupAfterGraphicsCall(false);
3414 void WebGLRenderingContext::stencilFunc(GC3Denum func, GC3Dint ref, GC3Duint mask)
3416 if (isContextLost())
3418 if (!validateStencilFunc("stencilFunc", func))
3420 m_stencilFuncRef = ref;
3421 m_stencilFuncRefBack = ref;
3422 m_stencilFuncMask = mask;
3423 m_stencilFuncMaskBack = mask;
3424 m_context->stencilFunc(func, ref, mask);
3425 cleanupAfterGraphicsCall(false);
3428 void WebGLRenderingContext::stencilFuncSeparate(GC3Denum face, GC3Denum func, GC3Dint ref, GC3Duint mask)
3430 if (isContextLost())
3432 if (!validateStencilFunc("stencilFuncSeparate", func))
3435 case GraphicsContext3D::FRONT_AND_BACK:
3436 m_stencilFuncRef = ref;
3437 m_stencilFuncRefBack = ref;
3438 m_stencilFuncMask = mask;
3439 m_stencilFuncMaskBack = mask;
3441 case GraphicsContext3D::FRONT:
3442 m_stencilFuncRef = ref;
3443 m_stencilFuncMask = mask;
3445 case GraphicsContext3D::BACK:
3446 m_stencilFuncRefBack = ref;
3447 m_stencilFuncMaskBack = mask;
3450 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "stencilFuncSeparate", "invalid face");
3453 m_context->stencilFuncSeparate(face, func, ref, mask);
3454 cleanupAfterGraphicsCall(false);
3457 void WebGLRenderingContext::stencilMask(GC3Duint mask)
3459 if (isContextLost())
3461 m_stencilMask = mask;
3462 m_stencilMaskBack = mask;
3463 m_context->stencilMask(mask);
3464 cleanupAfterGraphicsCall(false);
3467 void WebGLRenderingContext::stencilMaskSeparate(GC3Denum face, GC3Duint mask)
3469 if (isContextLost())
3472 case GraphicsContext3D::FRONT_AND_BACK:
3473 m_stencilMask = mask;
3474 m_stencilMaskBack = mask;
3476 case GraphicsContext3D::FRONT:
3477 m_stencilMask = mask;
3479 case GraphicsContext3D::BACK:
3480 m_stencilMaskBack = mask;
3483 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "stencilMaskSeparate", "invalid face");
3486 m_context->stencilMaskSeparate(face, mask);
3487 cleanupAfterGraphicsCall(false);
3490 void WebGLRenderingContext::stencilOp(GC3Denum fail, GC3Denum zfail, GC3Denum zpass)
3492 if (isContextLost())
3494 m_context->stencilOp(fail, zfail, zpass);
3495 cleanupAfterGraphicsCall(false);
3498 void WebGLRenderingContext::stencilOpSeparate(GC3Denum face, GC3Denum fail, GC3Denum zfail, GC3Denum zpass)
3500 if (isContextLost())
3502 m_context->stencilOpSeparate(face, fail, zfail, zpass);
3503 cleanupAfterGraphicsCall(false);
3506 void WebGLRenderingContext::texImage2DBase(GC3Denum target, GC3Dint level, GC3Denum internalformat,
3507 GC3Dsizei width, GC3Dsizei height, GC3Dint border,
3508 GC3Denum format, GC3Denum type, void* pixels, ExceptionCode& ec)
3510 // FIXME: For now we ignore any errors returned
3512 if (!validateTexFuncParameters("texImage2D", NotTexSubImage2D, target, level, internalformat, width, height, border, format, type))
3514 WebGLTexture* tex = validateTextureBinding("texImage2D", target, true);
3517 if (!isGLES2NPOTStrict()) {
3518 if (level && WebGLTexture::isNPOT(width, height)) {
3519 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "texImage2D", "level > 0 not power of 2");
3524 // Note: Chromium's OpenGL implementation clears textures and isResourceSafe() is therefore true.
3525 // For other implementations, if they are using ANGLE_depth_texture, ANGLE depth textures
3526 // can not be cleared with texImage2D and must be cleared by binding to an fbo and calling
3528 if (isResourceSafe())
3529 m_context->texImage2D(target, level, internalformat, width, height, border, format, type, 0);
3531 bool succeed = m_context->texImage2DResourceSafe(target, level, internalformat, width, height,
3532 border, format, type, m_unpackAlignment);
3537 if (!validateSettableTexFormat("texImage2D", internalformat))
3539 m_context->texImage2D(target, level, internalformat, width, height,
3540 border, format, type, pixels);
3542 tex->setLevelInfo(target, level, internalformat, width, height, type);
3543 cleanupAfterGraphicsCall(false);
3546 void WebGLRenderingContext::texImage2DImpl(GC3Denum target, GC3Dint level, GC3Denum internalformat,
3547 GC3Denum format, GC3Denum type, Image* image,
3548 bool flipY, bool premultiplyAlpha, ExceptionCode& ec)
3551 if (!validateSettableTexFormat("texImage2D", internalformat))
3553 Vector<uint8_t> data;
3554 if (!m_context->extractImageData(image, format, type, flipY, premultiplyAlpha, m_unpackColorspaceConversion == GraphicsContext3D::NONE, data)) {
3555 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "texImage2D", "bad image data");
3558 if (m_unpackAlignment != 1)
3559 m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, 1);
3560 #if ENABLE(TIZEN_JPEG_IMAGE_SCALE_DECODING)
3561 unsigned int componentsPerPixel;
3562 unsigned int bytesPerComponent;
3563 if (!GraphicsContext3D::computeFormatAndTypeParameters(format, type, &componentsPerPixel, &bytesPerComponent)) {
3564 ASSERT_NOT_REACHED();
3567 int dataSize = data.size() / (componentsPerPixel * bytesPerComponent);
3568 int imageSize = image->width() * image->height();
3569 if (dataSize != imageSize) {
3570 double scale = sqrt(static_cast<double>(dataSize) / imageSize);
3571 texImage2DBase(target, level, internalformat, image->width()*scale, image->height()*scale, 0,
3572 format, type, data.data(), ec);
3575 texImage2DBase(target, level, internalformat, image->width(), image->height(), 0,
3576 format, type, data.data(), ec);
3577 if (m_unpackAlignment != 1)
3578 m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, m_unpackAlignment);
3581 void WebGLRenderingContext::texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat,
3582 GC3Dsizei width, GC3Dsizei height, GC3Dint border,
3583 GC3Denum format, GC3Denum type, ArrayBufferView* pixels, ExceptionCode& ec)
3585 if (isContextLost() || !validateTexFuncData("texImage2D", level, width, height, format, type, pixels, NullAllowed))
3587 void* data = pixels ? pixels->baseAddress() : 0;
3588 Vector<uint8_t> tempData;
3589 bool changeUnpackAlignment = false;
3590 if (data && (m_unpackFlipY || m_unpackPremultiplyAlpha)) {
3591 if (!m_context->extractTextureData(width, height, format, type,
3593 m_unpackFlipY, m_unpackPremultiplyAlpha,
3597 data = tempData.data();
3598 changeUnpackAlignment = true;
3600 if (changeUnpackAlignment)
3601 m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, 1);
3602 texImage2DBase(target, level, internalformat, width, height, border,
3603 format, type, data, ec);
3604 if (changeUnpackAlignment)
3605 m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, m_unpackAlignment);
3608 void WebGLRenderingContext::texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat,
3609 GC3Denum format, GC3Denum type, ImageData* pixels, ExceptionCode& ec)
3612 if (isContextLost())
3614 Vector<uint8_t> data;
3617 bool needConversion = true;
3618 // The data from ImageData is always of format RGBA8.
3619 // No conversion is needed if destination format is RGBA and type is USIGNED_BYTE and no Flip or Premultiply operation is required.
3620 if (!m_unpackFlipY && !m_unpackPremultiplyAlpha && format == GraphicsContext3D::RGBA && type == GraphicsContext3D::UNSIGNED_BYTE)
3621 needConversion = false;
3623 if (!m_context->extractImageData(pixels, format, type, m_unpackFlipY, m_unpackPremultiplyAlpha, data)) {
3624 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "texImage2D", "bad image data");
3628 if (m_unpackAlignment != 1)
3629 m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, 1);
3630 texImage2DBase(target, level, internalformat, pixels->width(), pixels->height(), 0, format, type, needConversion ? data.data() : pixels->data()->data(), ec);
3631 if (m_unpackAlignment != 1)
3632 m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, m_unpackAlignment);
3635 void WebGLRenderingContext::texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat,
3636 GC3Denum format, GC3Denum type, HTMLImageElement* image, ExceptionCode& ec)
3639 if (isContextLost())
3641 if (!validateHTMLImageElement("texImage2D", image))
3643 if (wouldTaintOrigin(image)) {
3648 texImage2DImpl(target, level, internalformat, format, type, image->cachedImage()->imageForRenderer(image->renderer()),
3649 m_unpackFlipY, m_unpackPremultiplyAlpha, ec);
3652 void WebGLRenderingContext::texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat,
3653 GC3Denum format, GC3Denum type, HTMLCanvasElement* canvas, ExceptionCode& ec)
3656 if (isContextLost())
3658 if (!canvas || !canvas->buffer()) {
3659 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "texImage2D", "no canvas");
3662 if (wouldTaintOrigin(canvas)) {
3667 WebGLTexture* texture = validateTextureBinding("texImage2D", target, true);
3668 // If possible, copy from the canvas element directly to the texture
3669 // via the GPU, without a read-back to system memory.
3670 if (GraphicsContext3D::TEXTURE_2D == target && texture && type == texture->getType(target, level)) {
3671 ImageBuffer* buffer = canvas->buffer();
3672 if (buffer && buffer->copyToPlatformTexture(*m_context.get(), texture->object(), internalformat, m_unpackPremultiplyAlpha, m_unpackFlipY)) {
3673 texture->setLevelInfo(target, level, internalformat, canvas->width(), canvas->height(), type);
3674 cleanupAfterGraphicsCall(false);
3679 RefPtr<ImageData> imageData = canvas->getImageData();
3681 texImage2D(target, level, internalformat, format, type, imageData.get(), ec);
3683 texImage2DImpl(target, level, internalformat, format, type, canvas->copiedImage(),
3684 m_unpackFlipY, m_unpackPremultiplyAlpha, ec);
3688 PassRefPtr<Image> WebGLRenderingContext::videoFrameToImage(HTMLVideoElement* video, ExceptionCode& ec)
3690 if (!video || !video->videoWidth() || !video->videoHeight()) {
3691 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "texImage2D", "no video");
3694 IntSize size(video->videoWidth(), video->videoHeight());
3695 ImageBuffer* buf = m_videoCache.imageBuffer(size);
3697 synthesizeGLError(GraphicsContext3D::OUT_OF_MEMORY, "texImage2D", "out of memory");
3700 if (wouldTaintOrigin(video)) {
3704 IntRect destRect(0, 0, size.width(), size.height());
3705 // FIXME: Turn this into a GPU-GPU texture copy instead of CPU readback.
3706 video->paintCurrentFrameInContext(buf->context(), destRect);
3707 return buf->copyImage(CopyBackingStore);
3710 void WebGLRenderingContext::texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat,
3711 GC3Denum format, GC3Denum type, HTMLVideoElement* video, ExceptionCode& ec)
3714 if (isContextLost())
3716 RefPtr<Image> image = videoFrameToImage(video, ec);
3719 texImage2DImpl(target, level, internalformat, format, type, image.get(), m_unpackFlipY, m_unpackPremultiplyAlpha, ec);
3723 void WebGLRenderingContext::texParameter(GC3Denum target, GC3Denum pname, GC3Dfloat paramf, GC3Dint parami, bool isFloat)
3725 if (isContextLost())
3727 WebGLTexture* tex = validateTextureBinding("texParameter", target, false);
3731 case GraphicsContext3D::TEXTURE_MIN_FILTER:
3732 case GraphicsContext3D::TEXTURE_MAG_FILTER:
3734 case GraphicsContext3D::TEXTURE_WRAP_S:
3735 case GraphicsContext3D::TEXTURE_WRAP_T:
3736 if ((isFloat && paramf != GraphicsContext3D::CLAMP_TO_EDGE && paramf != GraphicsContext3D::MIRRORED_REPEAT && paramf != GraphicsContext3D::REPEAT)
3737 || (!isFloat && parami != GraphicsContext3D::CLAMP_TO_EDGE && parami != GraphicsContext3D::MIRRORED_REPEAT && parami != GraphicsContext3D::REPEAT)) {
3738 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "texParameter", "invalid parameter");
3742 case Extensions3D::TEXTURE_MAX_ANISOTROPY_EXT: // EXT_texture_filter_anisotropic
3743 if (!m_extTextureFilterAnisotropic) {
3744 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "texParameter", "invalid parameter, EXT_texture_filter_anisotropic not enabled");
3749 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "texParameter", "invalid parameter name");
3753 tex->setParameterf(pname, paramf);
3754 m_context->texParameterf(target, pname, paramf);
3756 tex->setParameteri(pname, parami);
3757 m_context->texParameteri(target, pname, parami);
3759 cleanupAfterGraphicsCall(false);
3762 void WebGLRenderingContext::texParameterf(GC3Denum target, GC3Denum pname, GC3Dfloat param)
3764 texParameter(target, pname, param, 0, true);
3767 void WebGLRenderingContext::texParameteri(GC3Denum target, GC3Denum pname, GC3Dint param)
3769 texParameter(target, pname, 0, param, false);
3772 void WebGLRenderingContext::texSubImage2DBase(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
3773 GC3Dsizei width, GC3Dsizei height,
3774 GC3Denum format, GC3Denum type, void* pixels, ExceptionCode& ec)
3776 // FIXME: For now we ignore any errors returned
3778 if (isContextLost())
3780 if (!validateTexFuncParameters("texSubImage2D", TexSubImage2D, target, level, format, width, height, 0, format, type))
3782 if (!validateSize("texSubImage2D", xoffset, yoffset))
3784 if (!validateSettableTexFormat("texSubImage2D", format))
3786 WebGLTexture* tex = validateTextureBinding("texSubImage2D", target, true);
3789 if (xoffset + width > tex->getWidth(target, level) || yoffset + height > tex->getHeight(target, level)) {
3790 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "texSubImage2D", "dimensions out of range");
3793 if (tex->getInternalFormat(target, level) != format || tex->getType(target, level) != type) {
3794 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "texSubImage2D", "type and format do not match texture");
3797 m_context->texSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels);
3798 cleanupAfterGraphicsCall(false);
3801 void WebGLRenderingContext::texSubImage2DImpl(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
3802 GC3Denum format, GC3Denum type,
3803 Image* image, bool flipY, bool premultiplyAlpha, ExceptionCode& ec)
3806 if (isContextLost())
3808 Vector<uint8_t> data;
3809 if (!m_context->extractImageData(image, format, type, flipY, premultiplyAlpha, m_unpackColorspaceConversion == GraphicsContext3D::NONE, data)) {
3810 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "texSubImage2D", "bad image");
3813 if (m_unpackAlignment != 1)
3814 m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, 1);
3815 texSubImage2DBase(target, level, xoffset, yoffset, image->width(), image->height(),
3816 format, type, data.data(), ec);
3817 if (m_unpackAlignment != 1)
3818 m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, m_unpackAlignment);
3821 void WebGLRenderingContext::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
3822 GC3Dsizei width, GC3Dsizei height,
3823 GC3Denum format, GC3Denum type, ArrayBufferView* pixels, ExceptionCode& ec)
3825 if (isContextLost() || !validateTexFuncData("texSubImage2D", level, width, height, format, type, pixels, NullNotAllowed))
3827 void* data = pixels->baseAddress();
3828 Vector<uint8_t> tempData;
3829 bool changeUnpackAlignment = false;
3830 if (data && (m_unpackFlipY || m_unpackPremultiplyAlpha)) {
3831 if (!m_context->extractTextureData(width, height, format, type,
3833 m_unpackFlipY, m_unpackPremultiplyAlpha,
3837 data = tempData.data();
3838 changeUnpackAlignment = true;
3840 if (changeUnpackAlignment)
3841 m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, 1);
3842 texSubImage2DBase(target, level, xoffset, yoffset, width, height, format, type, data, ec);
3843 if (changeUnpackAlignment)
3844 m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, m_unpackAlignment);
3847 void WebGLRenderingContext::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
3848 GC3Denum format, GC3Denum type, ImageData* pixels, ExceptionCode& ec)
3851 if (isContextLost())
3855 Vector<uint8_t> data;
3856 bool needConversion = true;
3857 // The data from ImageData is always of format RGBA8.
3858 // No conversion is needed if destination format is RGBA and type is USIGNED_BYTE and no Flip or Premultiply operation is required.
3859 if (format == GraphicsContext3D::RGBA && type == GraphicsContext3D::UNSIGNED_BYTE && !m_unpackFlipY && !m_unpackPremultiplyAlpha)
3860 needConversion = false;
3862 if (!m_context->extractImageData(pixels, format, type, m_unpackFlipY, m_unpackPremultiplyAlpha, data)) {
3863 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "texSubImage2D", "bad image data");
3867 if (m_unpackAlignment != 1)
3868 m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, 1);
3869 texSubImage2DBase(target, level, xoffset, yoffset, pixels->width(), pixels->height(), format, type, needConversion ? data.data() : pixels->data()->data(), ec);
3870 if (m_unpackAlignment != 1)
3871 m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, m_unpackAlignment);
3874 void WebGLRenderingContext::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
3875 GC3Denum format, GC3Denum type, HTMLImageElement* image, ExceptionCode& ec)
3878 if (isContextLost())
3880 if (!validateHTMLImageElement("texSubImage2D", image))
3882 if (wouldTaintOrigin(image)) {
3886 texSubImage2DImpl(target, level, xoffset, yoffset, format, type, image->cachedImage()->imageForRenderer(image->renderer()),
3887 m_unpackFlipY, m_unpackPremultiplyAlpha, ec);
3890 void WebGLRenderingContext::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
3891 GC3Denum format, GC3Denum type, HTMLCanvasElement* canvas, ExceptionCode& ec)
3894 if (isContextLost())
3896 if (!canvas || !canvas->buffer()) {
3897 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "texSubImage2D", "no canvas");
3900 if (wouldTaintOrigin(canvas)) {
3904 RefPtr<ImageData> imageData = canvas->getImageData();
3906 texSubImage2D(target, level, xoffset, yoffset, format, type, imageData.get(), ec);
3908 texSubImage2DImpl(target, level, xoffset, yoffset, format, type, canvas->copiedImage(),
3909 m_unpackFlipY, m_unpackPremultiplyAlpha, ec);
3913 void WebGLRenderingContext::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
3914 GC3Denum format, GC3Denum type, HTMLVideoElement* video, ExceptionCode& ec)
3917 if (isContextLost())
3919 RefPtr<Image> image = videoFrameToImage(video, ec);
3922 texSubImage2DImpl(target, level, xoffset, yoffset, format, type, image.get(), m_unpackFlipY, m_unpackPremultiplyAlpha, ec);
3926 void WebGLRenderingContext::uniform1f(const WebGLUniformLocation* location, GC3Dfloat x, ExceptionCode& ec)
3929 if (isContextLost() || !location)
3932 if (location->program() != m_currentProgram) {
3933 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "uniform1f", "location not for current program");
3937 m_context->uniform1f(location->location(), x);
3938 cleanupAfterGraphicsCall(false);
3941 void WebGLRenderingContext::uniform1fv(const WebGLUniformLocation* location, Float32Array* v, ExceptionCode& ec)
3944 if (isContextLost() || !validateUniformParameters("uniform1fv", location, v, 1))
3947 m_context->uniform1fv(location->location(), v->length(), v->data());
3948 cleanupAfterGraphicsCall(false);
3951 void WebGLRenderingContext::uniform1fv(const WebGLUniformLocation* location, GC3Dfloat* v, GC3Dsizei size, ExceptionCode& ec)
3954 if (isContextLost() || !validateUniformParameters("uniform1fv", location, v, size, 1))
3957 m_context->uniform1fv(location->location(), size, v);
3958 cleanupAfterGraphicsCall(false);
3961 void WebGLRenderingContext::uniform1i(const WebGLUniformLocation* location, GC3Dint x, ExceptionCode& ec)
3964 if (isContextLost() || !location)
3967 if (location->program() != m_currentProgram) {
3968 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "uniform1i", "location not for current program");
3972 m_context->uniform1i(location->location(), x);
3973 cleanupAfterGraphicsCall(false);
3976 void WebGLRenderingContext::uniform1iv(const WebGLUniformLocation* location, Int32Array* v, ExceptionCode& ec)
3979 if (isContextLost() || !validateUniformParameters("uniform1iv", location, v, 1))
3982 m_context->uniform1iv(location->location(), v->length(), v->data());
3983 cleanupAfterGraphicsCall(false);
3986 void WebGLRenderingContext::uniform1iv(const WebGLUniformLocation* location, GC3Dint* v, GC3Dsizei size, ExceptionCode& ec)
3989 if (isContextLost() || !validateUniformParameters("uniform1iv", location, v, size, 1))
3992 m_context->uniform1iv(location->location(), size, v);
3993 cleanupAfterGraphicsCall(false);
3996 void WebGLRenderingContext::uniform2f(const WebGLUniformLocation* location, GC3Dfloat x, GC3Dfloat y, ExceptionCode& ec)
3999 if (isContextLost() || !location)
4002 if (location->program() != m_currentProgram) {
4003 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "uniform2f", "location not for current program");
4007 m_context->uniform2f(location->location(), x, y);
4008 cleanupAfterGraphicsCall(false);
4011 void WebGLRenderingContext::uniform2fv(const WebGLUniformLocation* location, Float32Array* v, ExceptionCode& ec)
4014 if (isContextLost() || !validateUniformParameters("uniform2fv", location, v, 2))
4017 m_context->uniform2fv(location->location(), v->length() / 2, v->data());
4018 cleanupAfterGraphicsCall(false);
4021 void WebGLRenderingContext::uniform2fv(const WebGLUniformLocation* location, GC3Dfloat* v, GC3Dsizei size, ExceptionCode& ec)
4024 if (isContextLost() || !validateUniformParameters("uniform2fv", location, v, size, 2))
4027 m_context->uniform2fv(location->location(), size / 2, v);
4028 cleanupAfterGraphicsCall(false);
4031 void WebGLRenderingContext::uniform2i(const WebGLUniformLocation* location, GC3Dint x, GC3Dint y, ExceptionCode& ec)
4034 if (isContextLost() || !location)
4037 if (location->program() != m_currentProgram) {
4038 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "uniform2i", "location not for current program");
4042 m_context->uniform2i(location->location(), x, y);
4043 cleanupAfterGraphicsCall(false);
4046 void WebGLRenderingContext::uniform2iv(const WebGLUniformLocation* location, Int32Array* v, ExceptionCode& ec)
4049 if (isContextLost() || !validateUniformParameters("uniform2iv", location, v, 2))
4052 m_context->uniform2iv(location->location(), v->length() / 2, v->data());
4053 cleanupAfterGraphicsCall(false);
4056 void WebGLRenderingContext::uniform2iv(const WebGLUniformLocation* location, GC3Dint* v, GC3Dsizei size, ExceptionCode& ec)
4059 if (isContextLost() || !validateUniformParameters("uniform2iv", location, v, size, 2))
4062 m_context->uniform2iv(location->location(), size / 2, v);
4063 cleanupAfterGraphicsCall(false);
4066 void WebGLRenderingContext::uniform3f(const WebGLUniformLocation* location, GC3Dfloat x, GC3Dfloat y, GC3Dfloat z, ExceptionCode& ec)
4069 if (isContextLost() || !location)
4072 if (location->program() != m_currentProgram) {
4073 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "uniform3f", "location not for current program");
4077 m_context->uniform3f(location->location(), x, y, z);
4078 cleanupAfterGraphicsCall(false);
4081 void WebGLRenderingContext::uniform3fv(const WebGLUniformLocation* location, Float32Array* v, ExceptionCode& ec)
4084 if (isContextLost() || !validateUniformParameters("uniform3fv", location, v, 3))
4087 m_context->uniform3fv(location->location(), v->length() / 3, v->data());
4088 cleanupAfterGraphicsCall(false);
4091 void WebGLRenderingContext::uniform3fv(const WebGLUniformLocation* location, GC3Dfloat* v, GC3Dsizei size, ExceptionCode& ec)
4094 if (isContextLost() || !validateUniformParameters("uniform3fv", location, v, size, 3))
4097 m_context->uniform3fv(location->location(), size / 3, v);
4098 cleanupAfterGraphicsCall(false);
4101 void WebGLRenderingContext::uniform3i(const WebGLUniformLocation* location, GC3Dint x, GC3Dint y, GC3Dint z, ExceptionCode& ec)
4104 if (isContextLost() || !location)
4107 if (location->program() != m_currentProgram) {
4108 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "uniform3i", "location not for current program");
4112 m_context->uniform3i(location->location(), x, y, z);
4113 cleanupAfterGraphicsCall(false);
4116 void WebGLRenderingContext::uniform3iv(const WebGLUniformLocation* location, Int32Array* v, ExceptionCode& ec)
4119 if (isContextLost() || !validateUniformParameters("uniform3iv", location, v, 3))
4122 m_context->uniform3iv(location->location(), v->length() / 3, v->data());
4123 cleanupAfterGraphicsCall(false);
4126 void WebGLRenderingContext::uniform3iv(const WebGLUniformLocation* location, GC3Dint* v, GC3Dsizei size, ExceptionCode& ec)
4129 if (isContextLost() || !validateUniformParameters("uniform3iv", location, v, size, 3))
4132 m_context->uniform3iv(location->location(), size / 3, v);
4133 cleanupAfterGraphicsCall(false);
4136 void WebGLRenderingContext::uniform4f(const WebGLUniformLocation* location, GC3Dfloat x, GC3Dfloat y, GC3Dfloat z, GC3Dfloat w, ExceptionCode& ec)
4139 if (isContextLost() || !location)
4142 if (location->program() != m_currentProgram) {
4143 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "uniform4f", "location not for current program");
4147 m_context->uniform4f(location->location(), x, y, z, w);
4148 cleanupAfterGraphicsCall(false);
4151 void WebGLRenderingContext::uniform4fv(const WebGLUniformLocation* location, Float32Array* v, ExceptionCode& ec)
4154 if (isContextLost() || !validateUniformParameters("uniform4fv", location, v, 4))
4157 m_context->uniform4fv(location->location(), v->length() / 4, v->data());
4158 cleanupAfterGraphicsCall(false);
4161 void WebGLRenderingContext::uniform4fv(const WebGLUniformLocation* location, GC3Dfloat* v, GC3Dsizei size, ExceptionCode& ec)
4164 if (isContextLost() || !validateUniformParameters("uniform4fv", location, v, size, 4))
4167 m_context->uniform4fv(location->location(), size / 4, v);
4168 cleanupAfterGraphicsCall(false);
4171 void WebGLRenderingContext::uniform4i(const WebGLUniformLocation* location, GC3Dint x, GC3Dint y, GC3Dint z, GC3Dint w, ExceptionCode& ec)
4174 if (isContextLost() || !location)
4177 if (location->program() != m_currentProgram) {
4178 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "uniform4i", "location not for current program");
4182 m_context->uniform4i(location->location(), x, y, z, w);
4183 cleanupAfterGraphicsCall(false);
4186 void WebGLRenderingContext::uniform4iv(const WebGLUniformLocation* location, Int32Array* v, ExceptionCode& ec)
4189 if (isContextLost() || !validateUniformParameters("uniform4iv", location, v, 4))
4192 m_context->uniform4iv(location->location(), v->length() / 4, v->data());
4193 cleanupAfterGraphicsCall(false);
4196 void WebGLRenderingContext::uniform4iv(const WebGLUniformLocation* location, GC3Dint* v, GC3Dsizei size, ExceptionCode& ec)
4199 if (isContextLost() || !validateUniformParameters("uniform4iv", location, v, size, 4))
4202 m_context->uniform4iv(location->location(), size / 4, v);
4203 cleanupAfterGraphicsCall(false);
4206 void WebGLRenderingContext::uniformMatrix2fv(const WebGLUniformLocation* location, GC3Dboolean transpose, Float32Array* v, ExceptionCode& ec)
4209 if (isContextLost() || !validateUniformMatrixParameters("uniformMatrix2fv", location, transpose, v, 4))
4211 m_context->uniformMatrix2fv(location->location(), v->length() / 4, transpose, v->data());
4212 cleanupAfterGraphicsCall(false);
4215 void WebGLRenderingContext::uniformMatrix2fv(const WebGLUniformLocation* location, GC3Dboolean transpose, GC3Dfloat* v, GC3Dsizei size, ExceptionCode& ec)
4218 if (isContextLost() || !validateUniformMatrixParameters("uniformMatrix2fv", location, transpose, v, size, 4))
4220 m_context->uniformMatrix2fv(location->location(), size / 4, transpose, v);
4221 cleanupAfterGraphicsCall(false);
4224 void WebGLRenderingContext::uniformMatrix3fv(const WebGLUniformLocation* location, GC3Dboolean transpose, Float32Array* v, ExceptionCode& ec)
4227 if (isContextLost() || !validateUniformMatrixParameters("uniformMatrix3fv", location, transpose, v, 9))
4229 m_context->uniformMatrix3fv(location->location(), v->length() / 9, transpose, v->data());
4230 cleanupAfterGraphicsCall(false);
4233 void WebGLRenderingContext::uniformMatrix3fv(const WebGLUniformLocation* location, GC3Dboolean transpose, GC3Dfloat* v, GC3Dsizei size, ExceptionCode& ec)
4236 if (isContextLost() || !validateUniformMatrixParameters("uniformMatrix3fv", location, transpose, v, size, 9))
4238 m_context->uniformMatrix3fv(location->location(), size / 9, transpose, v);
4239 cleanupAfterGraphicsCall(false);
4242 void WebGLRenderingContext::uniformMatrix4fv(const WebGLUniformLocation* location, GC3Dboolean transpose, Float32Array* v, ExceptionCode& ec)
4245 if (isContextLost() || !validateUniformMatrixParameters("uniformMatrix4fv", location, transpose, v, 16))
4247 m_context->uniformMatrix4fv(location->location(), v->length() / 16, transpose, v->data());
4248 cleanupAfterGraphicsCall(false);
4251 void WebGLRenderingContext::uniformMatrix4fv(const WebGLUniformLocation* location, GC3Dboolean transpose, GC3Dfloat* v, GC3Dsizei size, ExceptionCode& ec)
4254 if (isContextLost() || !validateUniformMatrixParameters("uniformMatrix4fv", location, transpose, v, size, 16))
4256 m_context->uniformMatrix4fv(location->location(), size / 16, transpose, v);
4257 cleanupAfterGraphicsCall(false);
4260 void WebGLRenderingContext::useProgram(WebGLProgram* program, ExceptionCode& ec)
4264 if (!checkObjectToBeBound("useProgram", program, deleted))
4268 if (program && !program->getLinkStatus()) {
4269 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "useProgram", "program not valid");
4270 cleanupAfterGraphicsCall(false);
4273 if (m_currentProgram != program) {
4274 if (m_currentProgram)
4275 m_currentProgram->onDetached(graphicsContext3D());
4276 m_currentProgram = program;
4277 m_context->useProgram(objectOrZero(program));
4279 program->onAttached();
4281 cleanupAfterGraphicsCall(false);
4284 void WebGLRenderingContext::validateProgram(WebGLProgram* program, ExceptionCode& ec)
4287 if (isContextLost() || !validateWebGLObject("validateProgram", program))
4289 m_context->validateProgram(objectOrZero(program));
4290 cleanupAfterGraphicsCall(false);
4293 void WebGLRenderingContext::vertexAttrib1f(GC3Duint index, GC3Dfloat v0)
4295 vertexAttribfImpl("vertexAttrib1f", index, 1, v0, 0.0f, 0.0f, 1.0f);
4298 void WebGLRenderingContext::vertexAttrib1fv(GC3Duint index, Float32Array* v)
4300 vertexAttribfvImpl("vertexAttrib1fv", index, v, 1);
4303 void WebGLRenderingContext::vertexAttrib1fv(GC3Duint index, GC3Dfloat* v, GC3Dsizei size)
4305 vertexAttribfvImpl("vertexAttrib1fv", index, v, size, 1);
4308 void WebGLRenderingContext::vertexAttrib2f(GC3Duint index, GC3Dfloat v0, GC3Dfloat v1)
4310 vertexAttribfImpl("vertexAttrib2f", index, 2, v0, v1, 0.0f, 1.0f);
4313 void WebGLRenderingContext::vertexAttrib2fv(GC3Duint index, Float32Array* v)
4315 vertexAttribfvImpl("vertexAttrib2fv", index, v, 2);
4318 void WebGLRenderingContext::vertexAttrib2fv(GC3Duint index, GC3Dfloat* v, GC3Dsizei size)
4320 vertexAttribfvImpl("vertexAttrib2fv", index, v, size, 2);
4323 void WebGLRenderingContext::vertexAttrib3f(GC3Duint index, GC3Dfloat v0, GC3Dfloat v1, GC3Dfloat v2)
4325 vertexAttribfImpl("vertexAttrib3f", index, 3, v0, v1, v2, 1.0f);
4328 void WebGLRenderingContext::vertexAttrib3fv(GC3Duint index, Float32Array* v)
4330 vertexAttribfvImpl("vertexAttrib3fv", index, v, 3);
4333 void WebGLRenderingContext::vertexAttrib3fv(GC3Duint index, GC3Dfloat* v, GC3Dsizei size)
4335 vertexAttribfvImpl("vertexAttrib3fv", index, v, size, 3);
4338 void WebGLRenderingContext::vertexAttrib4f(GC3Duint index, GC3Dfloat v0, GC3Dfloat v1, GC3Dfloat v2, GC3Dfloat v3)
4340 vertexAttribfImpl("vertexAttrib4f", index, 4, v0, v1, v2, v3);
4343 void WebGLRenderingContext::vertexAttrib4fv(GC3Duint index, Float32Array* v)
4345 vertexAttribfvImpl("vertexAttrib4fv", index, v, 4);
4348 void WebGLRenderingContext::vertexAttrib4fv(GC3Duint index, GC3Dfloat* v, GC3Dsizei size)
4350 vertexAttribfvImpl("vertexAttrib4fv", index, v, size, 4);
4353 void WebGLRenderingContext::vertexAttribPointer(GC3Duint index, GC3Dint size, GC3Denum type, GC3Dboolean normalized, GC3Dsizei stride, long long offset, ExceptionCode& ec)
4356 if (isContextLost())
4359 case GraphicsContext3D::BYTE:
4360 case GraphicsContext3D::UNSIGNED_BYTE:
4361 case GraphicsContext3D::SHORT:
4362 case GraphicsContext3D::UNSIGNED_SHORT:
4363 case GraphicsContext3D::FLOAT:
4366 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "vertexAttribPointer", "invalid type");
4369 if (index >= m_maxVertexAttribs) {
4370 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "vertexAttribPointer", "index out of range");
4373 if (size < 1 || size > 4 || stride < 0 || stride > 255 || offset < 0) {
4374 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "vertexAttribPointer", "bad size, stride or offset");
4377 if (!m_boundArrayBuffer) {
4378 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "vertexAttribPointer", "no bound ARRAY_BUFFER");
4381 // Determine the number of elements the bound buffer can hold, given the offset, size, type and stride
4382 unsigned int typeSize = sizeInBytes(type);
4384 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "vertexAttribPointer", "invalid type");
4387 if ((stride % typeSize) || (static_cast<GC3Dintptr>(offset) % typeSize)) {
4388 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "vertexAttribPointer", "stride or offset not valid for type");
4391 GC3Dsizei bytesPerElement = size * typeSize;
4393 GC3Dsizei validatedStride = stride ? stride : bytesPerElement;
4395 WebGLVertexArrayObjectOES::VertexAttribState& state = m_boundVertexArrayObject->getVertexAttribState(index);
4396 state.bufferBinding = m_boundArrayBuffer;
4397 state.bytesPerElement = bytesPerElement;
4400 state.normalized = normalized;
4401 state.stride = validatedStride;
4402 state.originalStride = stride;
4403 state.offset = static_cast<GC3Dintptr>(offset);
4404 m_context->vertexAttribPointer(index, size, type, normalized, stride, static_cast<GC3Dintptr>(offset));
4405 cleanupAfterGraphicsCall(false);
4408 void WebGLRenderingContext::viewport(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height)
4410 if (isContextLost())
4412 if (!validateSize("viewport", width, height))
4414 m_context->viewport(x, y, width, height);
4415 cleanupAfterGraphicsCall(false);
4418 void WebGLRenderingContext::forceLostContext(WebGLRenderingContext::LostContextMode mode)
4420 if (isContextLost()) {
4421 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "loseContext", "context already lost");
4425 m_contextGroup->loseContextGroup(mode);
4428 void WebGLRenderingContext::loseContextImpl(WebGLRenderingContext::LostContextMode mode)
4430 if (isContextLost())
4433 m_contextLost = true;
4434 m_contextLostMode = mode;
4436 detachAndRemoveAllObjects();
4438 if (m_drawingBuffer) {
4439 // Make absolutely sure we do not refer to an already-deleted texture or framebuffer.
4440 m_drawingBuffer->setTexture2DBinding(0);
4441 m_drawingBuffer->setFramebufferBinding(0);
4444 // There is no direct way to clear errors from a GL implementation and
4445 // looping until getError() becomes NO_ERROR might cause an infinite loop if
4446 // the driver or context implementation had a bug. So, loop a reasonably
4447 // large number of times to clear any existing errors.
4448 for (int i = 0; i < 100; ++i) {
4449 if (m_context->getError() == GraphicsContext3D::NO_ERROR)
4452 synthesizeGLError(GraphicsContext3D::CONTEXT_LOST_WEBGL, "loseContext", "context lost");
4454 // Don't allow restoration unless the context lost event has both been
4455 // dispatched and its default behavior prevented.
4456 m_restoreAllowed = false;
4458 // Always defer the dispatch of the context lost event, to implement
4459 // the spec behavior of queueing a task.
4460 m_dispatchContextLostEventTimer.startOneShot(0);
4463 void WebGLRenderingContext::forceRestoreContext()
4465 if (!isContextLost()) {
4466 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "restoreContext", "context not lost");
4470 if (!m_restoreAllowed) {
4471 if (m_contextLostMode == SyntheticLostContext)
4472 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "restoreContext", "context restoration not allowed");
4476 if (!m_restoreTimer.isActive())
4477 m_restoreTimer.startOneShot(0);
4480 #if USE(ACCELERATED_COMPOSITING)
4481 PlatformLayer* WebGLRenderingContext::platformLayer() const
4483 #if PLATFORM(CHROMIUM)
4484 if (m_drawingBuffer)
4485 return m_drawingBuffer->platformLayer();
4488 return m_context->platformLayer();
4492 void WebGLRenderingContext::removeSharedObject(WebGLSharedObject* object)
4494 m_contextGroup->removeObject(object);
4497 void WebGLRenderingContext::addSharedObject(WebGLSharedObject* object)
4499 ASSERT(!isContextLost());
4500 m_contextGroup->addObject(object);
4503 void WebGLRenderingContext::removeContextObject(WebGLContextObject* object)
4505 m_contextObjects.remove(object);
4508 void WebGLRenderingContext::addContextObject(WebGLContextObject* object)
4510 ASSERT(!isContextLost());
4511 m_contextObjects.add(object);
4514 void WebGLRenderingContext::detachAndRemoveAllObjects()
4516 while (m_contextObjects.size() > 0) {
4517 HashSet<WebGLContextObject*>::iterator it = m_contextObjects.begin();
4518 (*it)->detachContext();
4522 WebGLGetInfo WebGLRenderingContext::getBooleanParameter(GC3Denum pname)
4524 GC3Dboolean value = 0;
4525 m_context->getBooleanv(pname, &value);
4526 return WebGLGetInfo(static_cast<bool>(value));
4529 WebGLGetInfo WebGLRenderingContext::getBooleanArrayParameter(GC3Denum pname)
4531 if (pname != GraphicsContext3D::COLOR_WRITEMASK) {
4533 return WebGLGetInfo(0, 0);
4535 GC3Dboolean value[4] = {0};
4536 m_context->getBooleanv(pname, value);
4538 for (int ii = 0; ii < 4; ++ii)
4539 boolValue[ii] = static_cast<bool>(value[ii]);
4540 return WebGLGetInfo(boolValue, 4);
4543 WebGLGetInfo WebGLRenderingContext::getFloatParameter(GC3Denum pname)
4545 GC3Dfloat value = 0;
4546 m_context->getFloatv(pname, &value);
4547 return WebGLGetInfo(value);
4550 WebGLGetInfo WebGLRenderingContext::getIntParameter(GC3Denum pname)
4553 m_context->getIntegerv(pname, &value);
4554 return WebGLGetInfo(value);
4557 WebGLGetInfo WebGLRenderingContext::getUnsignedIntParameter(GC3Denum pname)
4560 m_context->getIntegerv(pname, &value);
4561 return WebGLGetInfo(static_cast<unsigned int>(value));
4564 WebGLGetInfo WebGLRenderingContext::getWebGLFloatArrayParameter(GC3Denum pname)
4566 GC3Dfloat value[4] = {0};
4567 m_context->getFloatv(pname, value);
4568 unsigned length = 0;
4570 case GraphicsContext3D::ALIASED_POINT_SIZE_RANGE:
4571 case GraphicsContext3D::ALIASED_LINE_WIDTH_RANGE:
4572 case GraphicsContext3D::DEPTH_RANGE:
4575 case GraphicsContext3D::BLEND_COLOR:
4576 case GraphicsContext3D::COLOR_CLEAR_VALUE:
4582 return WebGLGetInfo(Float32Array::create(value, length));
4585 WebGLGetInfo WebGLRenderingContext::getWebGLIntArrayParameter(GC3Denum pname)
4587 GC3Dint value[4] = {0};
4588 m_context->getIntegerv(pname, value);
4589 unsigned length = 0;
4591 case GraphicsContext3D::MAX_VIEWPORT_DIMS:
4594 case GraphicsContext3D::SCISSOR_BOX:
4595 case GraphicsContext3D::VIEWPORT:
4601 return WebGLGetInfo(Int32Array::create(value, length));
4604 void WebGLRenderingContext::handleNPOTTextures(bool prepareToDraw)
4606 bool resetActiveUnit = false;
4607 for (unsigned ii = 0; ii < m_textureUnits.size(); ++ii) {
4608 if ((m_textureUnits[ii].m_texture2DBinding && m_textureUnits[ii].m_texture2DBinding->needToUseBlackTexture())
4609 || (m_textureUnits[ii].m_textureCubeMapBinding && m_textureUnits[ii].m_textureCubeMapBinding->needToUseBlackTexture())) {
4610 if (ii != m_activeTextureUnit) {
4611 m_context->activeTexture(ii);
4612 resetActiveUnit = true;
4613 } else if (resetActiveUnit) {
4614 m_context->activeTexture(ii);
4615 resetActiveUnit = false;
4617 WebGLTexture* tex2D;
4618 WebGLTexture* texCubeMap;
4619 if (prepareToDraw) {
4620 tex2D = m_blackTexture2D.get();
4621 texCubeMap = m_blackTextureCubeMap.get();
4623 tex2D = m_textureUnits[ii].m_texture2DBinding.get();
4624 texCubeMap = m_textureUnits[ii].m_textureCubeMapBinding.get();
4626 if (m_textureUnits[ii].m_texture2DBinding && m_textureUnits[ii].m_texture2DBinding->needToUseBlackTexture())
4627 m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, objectOrZero(tex2D));
4628 if (m_textureUnits[ii].m_textureCubeMapBinding && m_textureUnits[ii].m_textureCubeMapBinding->needToUseBlackTexture())
4629 m_context->bindTexture(GraphicsContext3D::TEXTURE_CUBE_MAP, objectOrZero(texCubeMap));
4632 if (resetActiveUnit)
4633 m_context->activeTexture(m_activeTextureUnit);
4636 void WebGLRenderingContext::createFallbackBlackTextures1x1()
4638 unsigned char black[] = {0, 0, 0, 255};
4639 m_blackTexture2D = createTexture();
4640 m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_blackTexture2D->object());
4641 m_context->texImage2D(GraphicsContext3D::TEXTURE_2D, 0, GraphicsContext3D::RGBA, 1, 1,
4642 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, black);
4643 m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, 0);
4644 m_blackTextureCubeMap = createTexture();
4645 m_context->bindTexture(GraphicsContext3D::TEXTURE_CUBE_MAP, m_blackTextureCubeMap->object());
4646 m_context->texImage2D(GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_X, 0, GraphicsContext3D::RGBA, 1, 1,
4647 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, black);
4648 m_context->texImage2D(GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GraphicsContext3D::RGBA, 1, 1,
4649 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, black);
4650 m_context->texImage2D(GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GraphicsContext3D::RGBA, 1, 1,
4651 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, black);
4652 m_context->texImage2D(GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GraphicsContext3D::RGBA, 1, 1,
4653 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, black);
4654 m_context->texImage2D(GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GraphicsContext3D::RGBA, 1, 1,
4655 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, black);
4656 m_context->texImage2D(GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GraphicsContext3D::RGBA, 1, 1,
4657 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, black);
4658 m_context->bindTexture(GraphicsContext3D::TEXTURE_CUBE_MAP, 0);
4661 bool WebGLRenderingContext::isTexInternalFormatColorBufferCombinationValid(GC3Denum texInternalFormat,
4662 GC3Denum colorBufferFormat)
4664 unsigned need = GraphicsContext3D::getChannelBitsByFormat(texInternalFormat);
4665 unsigned have = GraphicsContext3D::getChannelBitsByFormat(colorBufferFormat);
4666 return (need & have) == need;
4669 GC3Denum WebGLRenderingContext::getBoundFramebufferColorFormat()
4671 if (m_framebufferBinding && m_framebufferBinding->object())
4672 return m_framebufferBinding->getColorBufferFormat();
4673 if (m_attributes.alpha)
4674 return GraphicsContext3D::RGBA;
4675 return GraphicsContext3D::RGB;
4678 int WebGLRenderingContext::getBoundFramebufferWidth()
4680 if (m_framebufferBinding && m_framebufferBinding->object())
4681 return m_framebufferBinding->getColorBufferWidth();
4682 return m_drawingBuffer ? m_drawingBuffer->size().width() : m_context->getInternalFramebufferSize().width();
4685 int WebGLRenderingContext::getBoundFramebufferHeight()
4687 if (m_framebufferBinding && m_framebufferBinding->object())
4688 return m_framebufferBinding->getColorBufferHeight();
4689 return m_drawingBuffer ? m_drawingBuffer->size().height() : m_context->getInternalFramebufferSize().height();
4692 WebGLTexture* WebGLRenderingContext::validateTextureBinding(const char* functionName, GC3Denum target, bool useSixEnumsForCubeMap)
4694 WebGLTexture* tex = 0;
4696 case GraphicsContext3D::TEXTURE_2D:
4697 tex = m_textureUnits[m_activeTextureUnit].m_texture2DBinding.get();
4699 case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_X:
4700 case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_X:
4701 case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Y:
4702 case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Y:
4703 case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Z:
4704 case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Z:
4705 if (!useSixEnumsForCubeMap) {
4706 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid texture target");
4709 tex = m_textureUnits[m_activeTextureUnit].m_textureCubeMapBinding.get();
4711 case GraphicsContext3D::TEXTURE_CUBE_MAP:
4712 if (useSixEnumsForCubeMap) {
4713 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid texture target");
4716 tex = m_textureUnits[m_activeTextureUnit].m_textureCubeMapBinding.get();
4719 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid texture target");
4723 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "no texture");
4727 bool WebGLRenderingContext::validateLocationLength(const char* functionName, const String& string)
4729 const unsigned maxWebGLLocationLength = 256;
4730 if (string.length() > maxWebGLLocationLength) {
4731 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "location length > 256");
4737 bool WebGLRenderingContext::validateSize(const char* functionName, GC3Dint x, GC3Dint y)
4739 if (x < 0 || y < 0) {
4740 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "size < 0");
4746 bool WebGLRenderingContext::validateString(const char* functionName, const String& string)
4748 for (size_t i = 0; i < string.length(); ++i) {
4749 if (!validateCharacter(string[i])) {
4750 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "string not ASCII");
4757 bool WebGLRenderingContext::validateTexFuncFormatAndType(const char* functionName, GC3Denum format, GC3Denum type, GC3Dint level)
4760 case GraphicsContext3D::ALPHA:
4761 case GraphicsContext3D::LUMINANCE:
4762 case GraphicsContext3D::LUMINANCE_ALPHA:
4763 case GraphicsContext3D::RGB:
4764 case GraphicsContext3D::RGBA:
4766 case GraphicsContext3D::DEPTH_STENCIL:
4767 case GraphicsContext3D::DEPTH_COMPONENT:
4768 if (m_webglDepthTexture)
4770 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "depth texture formats not enabled");
4773 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid texture format");
4778 case GraphicsContext3D::UNSIGNED_BYTE:
4779 case GraphicsContext3D::UNSIGNED_SHORT_5_6_5:
4780 case GraphicsContext3D::UNSIGNED_SHORT_4_4_4_4:
4781 case GraphicsContext3D::UNSIGNED_SHORT_5_5_5_1:
4783 case GraphicsContext3D::FLOAT:
4784 if (m_oesTextureFloat)
4786 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid texture type");
4788 case GraphicsContext3D::UNSIGNED_INT:
4789 case GraphicsContext3D::UNSIGNED_INT_24_8:
4790 case GraphicsContext3D::UNSIGNED_SHORT:
4791 if (m_webglDepthTexture)
4793 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid texture type");
4796 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid texture type");
4800 // Verify that the combination of format and type is supported.
4802 case GraphicsContext3D::ALPHA:
4803 case GraphicsContext3D::LUMINANCE:
4804 case GraphicsContext3D::LUMINANCE_ALPHA:
4805 if (type != GraphicsContext3D::UNSIGNED_BYTE
4806 && type != GraphicsContext3D::FLOAT) {
4807 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "invalid type for format");
4811 case GraphicsContext3D::RGB:
4812 if (type != GraphicsContext3D::UNSIGNED_BYTE
4813 && type != GraphicsContext3D::UNSIGNED_SHORT_5_6_5
4814 && type != GraphicsContext3D::FLOAT) {
4815 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "invalid type for RGB format");
4819 case GraphicsContext3D::RGBA:
4820 if (type != GraphicsContext3D::UNSIGNED_BYTE
4821 && type != GraphicsContext3D::UNSIGNED_SHORT_4_4_4_4
4822 && type != GraphicsContext3D::UNSIGNED_SHORT_5_5_5_1
4823 && type != GraphicsContext3D::FLOAT) {
4824 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "invalid type for RGBA format");
4828 case GraphicsContext3D::DEPTH_COMPONENT:
4829 if (!m_webglDepthTexture) {
4830 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid format. DEPTH_COMPONENT not enabled");
4833 if (type != GraphicsContext3D::UNSIGNED_SHORT
4834 && type != GraphicsContext3D::UNSIGNED_INT) {
4835 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "invalid type for DEPTH_COMPONENT format");
4839 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "level must be 0 for DEPTH_COMPONENT format");
4843 case GraphicsContext3D::DEPTH_STENCIL:
4844 if (!m_webglDepthTexture) {
4845 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid format. DEPTH_STENCIL not enabled");
4848 if (type != GraphicsContext3D::UNSIGNED_INT_24_8) {
4849 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "invalid type for DEPTH_STENCIL format");
4853 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "level must be 0 for DEPTH_STENCIL format");
4858 ASSERT_NOT_REACHED();
4864 bool WebGLRenderingContext::validateTexFuncLevel(const char* functionName, GC3Denum target, GC3Dint level)
4867 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "level < 0");
4871 case GraphicsContext3D::TEXTURE_2D:
4872 if (level > m_maxTextureLevel) {
4873 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "level out of range");
4877 case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_X:
4878 case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_X:
4879 case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Y:
4880 case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Y:
4881 case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Z:
4882 case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Z:
4883 if (level > m_maxCubeMapTextureLevel) {
4884 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "level out of range");
4889 // This function only checks if level is legal, so we return true and don't
4890 // generate INVALID_ENUM if target is illegal.
4894 bool WebGLRenderingContext::validateTexFuncParameters(const char* functionName,
4895 TexFuncValidationFunctionType functionType,
4896 GC3Denum target, GC3Dint level,
4897 GC3Denum internalformat,
4898 GC3Dsizei width, GC3Dsizei height, GC3Dint border,
4899 GC3Denum format, GC3Denum type)
4901 // We absolutely have to validate the format and type combination.
4902 // The texImage2D entry points taking HTMLImage, etc. will produce
4903 // temporary data based on this combination, so it must be legal.
4904 if (!validateTexFuncFormatAndType(functionName, format, type, level) || !validateTexFuncLevel(functionName, target, level))
4907 if (width < 0 || height < 0) {
4908 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "width or height < 0");
4913 case GraphicsContext3D::TEXTURE_2D:
4914 if (width > m_maxTextureSize || height > m_maxTextureSize) {
4915 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "width or height out of range");
4919 case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_X:
4920 case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_X:
4921 case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Y:
4922 case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Y:
4923 case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Z:
4924 case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Z:
4925 if (functionType != TexSubImage2D && width != height) {
4926 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "width != height for cube map");
4929 // No need to check height here. For texImage width == height.
4930 // For texSubImage that will be checked when checking yoffset + height is in range.
4931 if (width > m_maxCubeMapTextureSize) {
4932 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "width or height out of range for cube map");
4937 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid target");
4941 if (format != internalformat) {
4942 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "format != internalformat");
4947 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "border != 0");
4954 bool WebGLRenderingContext::validateTexFuncData(const char* functionName, GC3Dint level,
4955 GC3Dsizei width, GC3Dsizei height,
4956 GC3Denum format, GC3Denum type,
4957 ArrayBufferView* pixels,
4958 NullDisposition disposition)
4961 if (disposition == NullAllowed)
4963 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "no pixels");
4967 if (!validateTexFuncFormatAndType(functionName, format, type, level))
4969 if (!validateSettableTexFormat(functionName, format))
4973 case GraphicsContext3D::UNSIGNED_BYTE:
4974 if (pixels->getType() != ArrayBufferView::TypeUint8) {
4975 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "type UNSIGNED_BYTE but ArrayBufferView not Uint8Array");
4979 case GraphicsContext3D::UNSIGNED_SHORT_5_6_5:
4980 case GraphicsContext3D::UNSIGNED_SHORT_4_4_4_4:
4981 case GraphicsContext3D::UNSIGNED_SHORT_5_5_5_1:
4982 if (pixels->getType() != ArrayBufferView::TypeUint16) {
4983 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "type UNSIGNED_SHORT but ArrayBufferView not Uint16Array");
4987 case GraphicsContext3D::FLOAT: // OES_texture_float
4988 if (pixels->getType() != ArrayBufferView::TypeFloat32) {
4989 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "type FLOAT but ArrayBufferView not Float32Array");
4994 ASSERT_NOT_REACHED();
4997 unsigned int totalBytesRequired;
4998 GC3Denum error = m_context->computeImageSizeInBytes(format, type, width, height, m_unpackAlignment, &totalBytesRequired, 0);
4999 if (error != GraphicsContext3D::NO_ERROR) {
5000 synthesizeGLError(error, functionName, "invalid texture dimensions");
5003 if (pixels->byteLength() < totalBytesRequired) {
5004 if (m_unpackAlignment != 1) {
5005 error = m_context->computeImageSizeInBytes(format, type, width, height, 1, &totalBytesRequired, 0);
5006 if (pixels->byteLength() == totalBytesRequired) {
5007 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "ArrayBufferView not big enough for request with UNPACK_ALIGNMENT > 1");
5011 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "ArrayBufferView not big enough for request");
5017 bool WebGLRenderingContext::validateCompressedTexFormat(GC3Denum format)
5019 return m_compressedTextureFormats.contains(format);
5022 bool WebGLRenderingContext::validateCompressedTexFuncData(const char* functionName,
5023 GC3Dsizei width, GC3Dsizei height,
5024 GC3Denum format, ArrayBufferView* pixels)
5027 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "no pixels");
5030 if (width < 0 || height < 0) {
5031 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "width or height < 0");
5035 unsigned int bytesRequired = 0;
5038 case Extensions3D::COMPRESSED_RGB_S3TC_DXT1_EXT:
5039 case Extensions3D::COMPRESSED_RGBA_S3TC_DXT1_EXT:
5041 const int kBlockWidth = 4;
5042 const int kBlockHeight = 4;
5043 const int kBlockSize = 8;
5044 int numBlocksAcross = (width + kBlockWidth - 1) / kBlockWidth;
5045 int numBlocksDown = (height + kBlockHeight - 1) / kBlockHeight;
5046 int numBlocks = numBlocksAcross * numBlocksDown;
5047 bytesRequired = numBlocks * kBlockSize;
5050 case Extensions3D::COMPRESSED_RGBA_S3TC_DXT3_EXT:
5051 case Extensions3D::COMPRESSED_RGBA_S3TC_DXT5_EXT:
5053 const int kBlockWidth = 4;
5054 const int kBlockHeight = 4;
5055 const int kBlockSize = 16;
5056 int numBlocksAcross = (width + kBlockWidth - 1) / kBlockWidth;
5057 int numBlocksDown = (height + kBlockHeight - 1) / kBlockHeight;
5058 int numBlocks = numBlocksAcross * numBlocksDown;
5059 bytesRequired = numBlocks * kBlockSize;
5063 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid format");
5067 if (pixels->byteLength() != bytesRequired) {
5068 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "length of ArrayBufferView is not correct for dimensions");
5075 bool WebGLRenderingContext::validateCompressedTexDimensions(const char* functionName, GC3Dint level, GC3Dsizei width, GC3Dsizei height, GC3Denum format)
5078 case Extensions3D::COMPRESSED_RGB_S3TC_DXT1_EXT:
5079 case Extensions3D::COMPRESSED_RGBA_S3TC_DXT1_EXT:
5080 case Extensions3D::COMPRESSED_RGBA_S3TC_DXT3_EXT:
5081 case Extensions3D::COMPRESSED_RGBA_S3TC_DXT5_EXT: {
5082 const int kBlockWidth = 4;
5083 const int kBlockHeight = 4;
5084 bool widthValid = (level && width == 1) || (level && width == 2) || !(width % kBlockWidth);
5085 bool heightValid = (level && height == 1) || (level && height == 2) || !(height % kBlockHeight);
5086 if (!widthValid || !heightValid) {
5087 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "width or height invalid for level");
5097 bool WebGLRenderingContext::validateCompressedTexSubDimensions(const char* functionName, GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
5098 GC3Dsizei width, GC3Dsizei height, GC3Denum format, WebGLTexture* tex)
5100 if (xoffset < 0 || yoffset < 0) {
5101 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "xoffset or yoffset < 0");
5106 case Extensions3D::COMPRESSED_RGB_S3TC_DXT1_EXT:
5107 case Extensions3D::COMPRESSED_RGBA_S3TC_DXT1_EXT:
5108 case Extensions3D::COMPRESSED_RGBA_S3TC_DXT3_EXT:
5109 case Extensions3D::COMPRESSED_RGBA_S3TC_DXT5_EXT: {
5110 const int kBlockWidth = 4;
5111 const int kBlockHeight = 4;
5112 if ((xoffset % kBlockWidth) || (yoffset % kBlockHeight)) {
5113 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "xoffset or yoffset not multiple of 4");
5116 if (width - xoffset > tex->getWidth(target, level)
5117 || height - yoffset > tex->getHeight(target, level)) {
5118 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "dimensions out of range");
5121 return validateCompressedTexDimensions(functionName, level, width, height, format);
5128 bool WebGLRenderingContext::validateDrawMode(const char* functionName, GC3Denum mode)
5131 case GraphicsContext3D::POINTS:
5132 case GraphicsContext3D::LINE_STRIP:
5133 case GraphicsContext3D::LINE_LOOP:
5134 case GraphicsContext3D::LINES:
5135 case GraphicsContext3D::TRIANGLE_STRIP:
5136 case GraphicsContext3D::TRIANGLE_FAN:
5137 case GraphicsContext3D::TRIANGLES:
5140 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid draw mode");
5145 bool WebGLRenderingContext::validateStencilSettings(const char* functionName)
5147 if (m_stencilMask != m_stencilMaskBack || m_stencilFuncRef != m_stencilFuncRefBack || m_stencilFuncMask != m_stencilFuncMaskBack) {
5148 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "front and back stencils settings do not match");
5154 bool WebGLRenderingContext::validateStencilFunc(const char* functionName, GC3Denum func)
5157 case GraphicsContext3D::NEVER:
5158 case GraphicsContext3D::LESS:
5159 case GraphicsContext3D::LEQUAL:
5160 case GraphicsContext3D::GREATER:
5161 case GraphicsContext3D::GEQUAL:
5162 case GraphicsContext3D::EQUAL:
5163 case GraphicsContext3D::NOTEQUAL:
5164 case GraphicsContext3D::ALWAYS:
5167 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid function");
5172 void WebGLRenderingContext::printGLErrorToConsole(const String& message)
5174 if (!m_numGLErrorsToConsoleAllowed)
5177 --m_numGLErrorsToConsoleAllowed;
5178 printWarningToConsole(message);
5180 if (!m_numGLErrorsToConsoleAllowed)
5181 printWarningToConsole("WebGL: too many errors, no more errors will be reported to the console for this context.");
5184 void WebGLRenderingContext::printWarningToConsole(const String& message)
5188 Document* document = canvas()->document();
5191 Frame* frame = document->frame();
5194 DOMWindow* window = frame->domWindow();
5197 Console* console = window->console();
5200 console->addMessage(HTMLMessageSource, LogMessageType, WarningMessageLevel, message, document->url().string());
5203 bool WebGLRenderingContext::validateFramebufferFuncParameters(const char* functionName, GC3Denum target, GC3Denum attachment)
5205 if (target != GraphicsContext3D::FRAMEBUFFER) {
5206 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid target");
5209 switch (attachment) {
5210 case GraphicsContext3D::COLOR_ATTACHMENT0:
5211 case GraphicsContext3D::DEPTH_ATTACHMENT:
5212 case GraphicsContext3D::STENCIL_ATTACHMENT:
5213 case GraphicsContext3D::DEPTH_STENCIL_ATTACHMENT:
5216 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid attachment");
5222 bool WebGLRenderingContext::validateBlendEquation(const char* functionName, GC3Denum mode)
5225 case GraphicsContext3D::FUNC_ADD:
5226 case GraphicsContext3D::FUNC_SUBTRACT:
5227 case GraphicsContext3D::FUNC_REVERSE_SUBTRACT:
5230 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid mode");
5235 bool WebGLRenderingContext::validateBlendFuncFactors(const char* functionName, GC3Denum src, GC3Denum dst)
5237 if (((src == GraphicsContext3D::CONSTANT_COLOR || src == GraphicsContext3D::ONE_MINUS_CONSTANT_COLOR)
5238 && (dst == GraphicsContext3D::CONSTANT_ALPHA || dst == GraphicsContext3D::ONE_MINUS_CONSTANT_ALPHA))
5239 || ((dst == GraphicsContext3D::CONSTANT_COLOR || dst == GraphicsContext3D::ONE_MINUS_CONSTANT_COLOR)
5240 && (src == GraphicsContext3D::CONSTANT_ALPHA || src == GraphicsContext3D::ONE_MINUS_CONSTANT_ALPHA))) {
5241 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "incompatible src and dst");
5247 bool WebGLRenderingContext::validateCapability(const char* functionName, GC3Denum cap)
5250 case GraphicsContext3D::BLEND:
5251 case GraphicsContext3D::CULL_FACE:
5252 case GraphicsContext3D::DEPTH_TEST:
5253 case GraphicsContext3D::DITHER:
5254 case GraphicsContext3D::POLYGON_OFFSET_FILL:
5255 case GraphicsContext3D::SAMPLE_ALPHA_TO_COVERAGE:
5256 case GraphicsContext3D::SAMPLE_COVERAGE:
5257 case GraphicsContext3D::SCISSOR_TEST:
5258 case GraphicsContext3D::STENCIL_TEST:
5261 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid capability");
5266 bool WebGLRenderingContext::validateUniformParameters(const char* functionName, const WebGLUniformLocation* location, Float32Array* v, GC3Dsizei requiredMinSize)
5269 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "no array");
5272 return validateUniformMatrixParameters(functionName, location, false, v->data(), v->length(), requiredMinSize);
5275 bool WebGLRenderingContext::validateUniformParameters(const char* functionName, const WebGLUniformLocation* location, Int32Array* v, GC3Dsizei requiredMinSize)
5278 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "no array");
5281 return validateUniformMatrixParameters(functionName, location, false, v->data(), v->length(), requiredMinSize);
5284 bool WebGLRenderingContext::validateUniformParameters(const char* functionName, const WebGLUniformLocation* location, void* v, GC3Dsizei size, GC3Dsizei requiredMinSize)
5286 return validateUniformMatrixParameters(functionName, location, false, v, size, requiredMinSize);
5289 bool WebGLRenderingContext::validateUniformMatrixParameters(const char* functionName, const WebGLUniformLocation* location, GC3Dboolean transpose, Float32Array* v, GC3Dsizei requiredMinSize)
5292 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "no array");
5295 return validateUniformMatrixParameters(functionName, location, transpose, v->data(), v->length(), requiredMinSize);
5298 bool WebGLRenderingContext::validateUniformMatrixParameters(const char* functionName, const WebGLUniformLocation* location, GC3Dboolean transpose, void* v, GC3Dsizei size, GC3Dsizei requiredMinSize)
5302 if (location->program() != m_currentProgram) {
5303 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "location is not from current program");
5307 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "no array");
5311 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "transpose not FALSE");
5314 if (size < requiredMinSize || (size % requiredMinSize)) {
5315 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "invalid size");
5321 WebGLBuffer* WebGLRenderingContext::validateBufferDataParameters(const char* functionName, GC3Denum target, GC3Denum usage)
5323 WebGLBuffer* buffer = 0;
5325 case GraphicsContext3D::ELEMENT_ARRAY_BUFFER:
5326 buffer = m_boundVertexArrayObject->getElementArrayBuffer().get();
5328 case GraphicsContext3D::ARRAY_BUFFER:
5329 buffer = m_boundArrayBuffer.get();
5332 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid target");
5336 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "no buffer");
5340 case GraphicsContext3D::STREAM_DRAW:
5341 case GraphicsContext3D::STATIC_DRAW:
5342 case GraphicsContext3D::DYNAMIC_DRAW:
5345 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid usage");
5349 bool WebGLRenderingContext::validateHTMLImageElement(const char* functionName, HTMLImageElement* image)
5351 if (!image || !image->cachedImage()) {
5352 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "no image");
5355 const KURL& url = image->cachedImage()->response().url();
5356 if (url.isNull() || url.isEmpty() || !url.isValid()) {
5357 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "invalid image");
5363 void WebGLRenderingContext::vertexAttribfImpl(const char* functionName, GC3Duint index, GC3Dsizei expectedSize, GC3Dfloat v0, GC3Dfloat v1, GC3Dfloat v2, GC3Dfloat v3)
5365 if (isContextLost())
5367 if (index >= m_maxVertexAttribs) {
5368 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "index out of range");
5371 // In GL, we skip setting vertexAttrib0 values.
5372 if (index || isGLES2Compliant()) {
5373 switch (expectedSize) {
5375 m_context->vertexAttrib1f(index, v0);
5378 m_context->vertexAttrib2f(index, v0, v1);
5381 m_context->vertexAttrib3f(index, v0, v1, v2);
5384 m_context->vertexAttrib4f(index, v0, v1, v2, v3);
5387 cleanupAfterGraphicsCall(false);
5389 VertexAttribValue& attribValue = m_vertexAttribValue[index];
5390 attribValue.value[0] = v0;
5391 attribValue.value[1] = v1;
5392 attribValue.value[2] = v2;
5393 attribValue.value[3] = v3;
5396 void WebGLRenderingContext::vertexAttribfvImpl(const char* functionName, GC3Duint index, Float32Array* v, GC3Dsizei expectedSize)
5398 if (isContextLost())
5401 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "no array");
5404 vertexAttribfvImpl(functionName, index, v->data(), v->length(), expectedSize);
5407 void WebGLRenderingContext::vertexAttribfvImpl(const char* functionName, GC3Duint index, GC3Dfloat* v, GC3Dsizei size, GC3Dsizei expectedSize)
5409 if (isContextLost())
5412 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "no array");
5415 if (size < expectedSize) {
5416 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "invalid size");
5419 if (index >= m_maxVertexAttribs) {
5420 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "index out of range");
5423 // In GL, we skip setting vertexAttrib0 values.
5424 if (index || isGLES2Compliant()) {
5425 switch (expectedSize) {
5427 m_context->vertexAttrib1fv(index, v);
5430 m_context->vertexAttrib2fv(index, v);
5433 m_context->vertexAttrib3fv(index, v);
5436 m_context->vertexAttrib4fv(index, v);
5439 cleanupAfterGraphicsCall(false);
5441 VertexAttribValue& attribValue = m_vertexAttribValue[index];
5442 attribValue.initValue();
5443 for (int ii = 0; ii < expectedSize; ++ii)
5444 attribValue.value[ii] = v[ii];
5447 void WebGLRenderingContext::initVertexAttrib0()
5449 WebGLVertexArrayObjectOES::VertexAttribState& state = m_boundVertexArrayObject->getVertexAttribState(0);
5451 m_vertexAttrib0Buffer = createBuffer();
5452 m_context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, m_vertexAttrib0Buffer->object());
5453 m_context->bufferData(GraphicsContext3D::ARRAY_BUFFER, 0, GraphicsContext3D::DYNAMIC_DRAW);
5454 m_context->vertexAttribPointer(0, 4, GraphicsContext3D::FLOAT, false, 0, 0);
5455 state.bufferBinding = m_vertexAttrib0Buffer;
5456 m_context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, 0);
5457 m_context->enableVertexAttribArray(0);
5458 m_vertexAttrib0BufferSize = 0;
5459 m_vertexAttrib0BufferValue[0] = 0.0f;
5460 m_vertexAttrib0BufferValue[1] = 0.0f;
5461 m_vertexAttrib0BufferValue[2] = 0.0f;
5462 m_vertexAttrib0BufferValue[3] = 1.0f;
5463 m_forceAttrib0BufferRefill = false;
5464 m_vertexAttrib0UsedBefore = false;
5467 bool WebGLRenderingContext::simulateVertexAttrib0(GC3Dsizei numVertex)
5469 const WebGLVertexArrayObjectOES::VertexAttribState& state = m_boundVertexArrayObject->getVertexAttribState(0);
5470 const VertexAttribValue& attribValue = m_vertexAttribValue[0];
5471 if (!m_currentProgram)
5473 bool usingVertexAttrib0 = m_currentProgram->isUsingVertexAttrib0();
5474 if (usingVertexAttrib0)
5475 m_vertexAttrib0UsedBefore = true;
5476 if (state.enabled && usingVertexAttrib0)
5478 if (!usingVertexAttrib0 && !m_vertexAttrib0UsedBefore)
5480 m_vertexAttrib0UsedBefore = true;
5481 m_context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, m_vertexAttrib0Buffer->object());
5482 GC3Dsizeiptr bufferDataSize = (numVertex + 1) * 4 * sizeof(GC3Dfloat);
5483 if (bufferDataSize > m_vertexAttrib0BufferSize) {
5484 m_context->bufferData(GraphicsContext3D::ARRAY_BUFFER, bufferDataSize, 0, GraphicsContext3D::DYNAMIC_DRAW);
5485 m_vertexAttrib0BufferSize = bufferDataSize;
5486 m_forceAttrib0BufferRefill = true;
5488 if (usingVertexAttrib0
5489 && (m_forceAttrib0BufferRefill
5490 || attribValue.value[0] != m_vertexAttrib0BufferValue[0]
5491 || attribValue.value[1] != m_vertexAttrib0BufferValue[1]
5492 || attribValue.value[2] != m_vertexAttrib0BufferValue[2]
5493 || attribValue.value[3] != m_vertexAttrib0BufferValue[3])) {
5494 OwnArrayPtr<GC3Dfloat> bufferData = adoptArrayPtr(new GC3Dfloat[(numVertex + 1) * 4]);
5495 for (GC3Dsizei ii = 0; ii < numVertex + 1; ++ii) {
5496 bufferData[ii * 4] = attribValue.value[0];
5497 bufferData[ii * 4 + 1] = attribValue.value[1];
5498 bufferData[ii * 4 + 2] = attribValue.value[2];
5499 bufferData[ii * 4 + 3] = attribValue.value[3];
5501 m_vertexAttrib0BufferValue[0] = attribValue.value[0];
5502 m_vertexAttrib0BufferValue[1] = attribValue.value[1];
5503 m_vertexAttrib0BufferValue[2] = attribValue.value[2];
5504 m_vertexAttrib0BufferValue[3] = attribValue.value[3];
5505 m_forceAttrib0BufferRefill = false;
5506 m_context->bufferSubData(GraphicsContext3D::ARRAY_BUFFER, 0, bufferDataSize, bufferData.get());
5508 m_context->vertexAttribPointer(0, 4, GraphicsContext3D::FLOAT, 0, 0, 0);
5512 void WebGLRenderingContext::restoreStatesAfterVertexAttrib0Simulation()
5514 const WebGLVertexArrayObjectOES::VertexAttribState& state = m_boundVertexArrayObject->getVertexAttribState(0);
5515 if (state.bufferBinding != m_vertexAttrib0Buffer) {
5516 m_context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, objectOrZero(state.bufferBinding.get()));
5517 m_context->vertexAttribPointer(0, state.size, state.type, state.normalized, state.originalStride, state.offset);
5519 m_context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, objectOrZero(m_boundArrayBuffer.get()));
5522 void WebGLRenderingContext::dispatchContextLostEvent(Timer<WebGLRenderingContext>*)
5524 RefPtr<WebGLContextEvent> event = WebGLContextEvent::create(eventNames().webglcontextlostEvent, false, true, "");
5525 canvas()->dispatchEvent(event);
5526 m_restoreAllowed = event->defaultPrevented();
5527 if (m_contextLostMode == RealLostContext && m_restoreAllowed)
5528 m_restoreTimer.startOneShot(0);
5531 void WebGLRenderingContext::maybeRestoreContext(Timer<WebGLRenderingContext>*)
5533 ASSERT(m_contextLost);
5537 // The rendering context is not restored unless the default behavior of the
5538 // webglcontextlost event was prevented earlier.
5540 // Because of the way m_restoreTimer is set up for real vs. synthetic lost
5541 // context events, we don't have to worry about this test short-circuiting
5542 // the retry loop for real context lost events.
5543 if (!m_restoreAllowed)
5546 int contextLostReason = m_context->getExtensions()->getGraphicsResetStatusARB();
5548 switch (contextLostReason) {
5549 case GraphicsContext3D::NO_ERROR:
5550 // The GraphicsContext3D implementation might not fully
5551 // support GL_ARB_robustness semantics yet. Alternatively, the
5552 // WEBGL_lose_context extension might have been used to force
5555 case Extensions3D::GUILTY_CONTEXT_RESET_ARB:
5556 // The rendering context is not restored if this context was
5557 // guilty of causing the graphics reset.
5558 printWarningToConsole("WARNING: WebGL content on the page caused the graphics card to reset; not restoring the context");
5560 case Extensions3D::INNOCENT_CONTEXT_RESET_ARB:
5561 // Always allow the context to be restored.
5563 case Extensions3D::UNKNOWN_CONTEXT_RESET_ARB:
5564 // Warn. Ideally, prompt the user telling them that WebGL
5565 // content on the page might have caused the graphics card to
5566 // reset and ask them whether they want to continue running
5567 // the content. Only if they say "yes" should we start
5568 // attempting to restore the context.
5569 printWarningToConsole("WARNING: WebGL content on the page might have caused the graphics card to reset");
5573 RefPtr<GraphicsContext3D> context(GraphicsContext3D::create(m_attributes, canvas()->document()->view()->root()->hostWindow()));
5575 if (m_contextLostMode == RealLostContext)
5576 m_restoreTimer.startOneShot(secondsBetweenRestoreAttempts);
5578 // This likely shouldn't happen but is the best way to report it to the WebGL app.
5579 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "", "error restoring context");
5583 // Construct a new drawing buffer with the new GraphicsContext3D.
5584 if (m_drawingBuffer) {
5585 m_drawingBuffer->discardResources();
5586 DrawingBuffer::PreserveDrawingBuffer preserve = m_attributes.preserveDrawingBuffer ? DrawingBuffer::Preserve : DrawingBuffer::Discard;
5587 DrawingBuffer::AlphaRequirement alpha = m_attributes.alpha ? DrawingBuffer::Alpha : DrawingBuffer::Opaque;
5588 m_drawingBuffer = DrawingBuffer::create(context.get(), m_drawingBuffer->size(), preserve, alpha);
5589 m_drawingBuffer->bind();
5592 m_context = context;
5593 m_contextLost = false;
5594 initializeNewContext();
5595 canvas()->dispatchEvent(WebGLContextEvent::create(eventNames().webglcontextrestoredEvent, false, true, ""));
5598 String WebGLRenderingContext::ensureNotNull(const String& text) const
5601 return WTF::emptyString();
5605 WebGLRenderingContext::LRUImageBufferCache::LRUImageBufferCache(int capacity)
5606 : m_buffers(adoptArrayPtr(new OwnPtr<ImageBuffer>[capacity]))
5607 , m_capacity(capacity)
5611 ImageBuffer* WebGLRenderingContext::LRUImageBufferCache::imageBuffer(const IntSize& size)
5614 for (i = 0; i < m_capacity; ++i) {
5615 ImageBuffer* buf = m_buffers[i].get();
5618 if (buf->logicalSize() != size)
5624 OwnPtr<ImageBuffer> temp = ImageBuffer::create(size, 1);
5627 i = std::min(m_capacity - 1, i);
5628 m_buffers[i] = temp.release();
5630 ImageBuffer* buf = m_buffers[i].get();
5635 void WebGLRenderingContext::LRUImageBufferCache::bubbleToFront(int idx)
5637 for (int i = idx; i > 0; --i)
5638 m_buffers[i].swap(m_buffers[i-1]);
5643 String GetErrorString(GC3Denum error)
5646 case GraphicsContext3D::INVALID_ENUM:
5647 return "INVALID_ENUM";
5648 case GraphicsContext3D::INVALID_VALUE:
5649 return "INVALID_VALUE";
5650 case GraphicsContext3D::INVALID_OPERATION:
5651 return "INVALID_OPERATION";
5652 case GraphicsContext3D::OUT_OF_MEMORY:
5653 return "OUT_OF_MEMORY";
5654 case GraphicsContext3D::INVALID_FRAMEBUFFER_OPERATION:
5655 return "INVALID_FRAMEBUFFER_OPERATION";
5656 case GraphicsContext3D::CONTEXT_LOST_WEBGL:
5657 return "CONTEXT_LOST_WEBGL";
5659 return String::format("WebGL ERROR(%04x)", error);
5663 } // namespace anonymous
5665 void WebGLRenderingContext::synthesizeGLError(GC3Denum error, const char* functionName, const char* description)
5667 if (m_synthesizedErrorsToConsole) {
5668 String str = String("WebGL: ") + GetErrorString(error) + ": " + String(functionName) + ": " + String(description);
5669 printGLErrorToConsole(str);
5671 m_context->synthesizeGLError(error);
5675 void WebGLRenderingContext::printGLWarningToConsole(const char* functionName, const char* description)
5677 if (m_synthesizedErrorsToConsole) {
5678 String str = String("WebGL: ") + String(functionName) + ": " + String(description);
5679 printGLErrorToConsole(str);
5683 void WebGLRenderingContext::applyStencilTest()
5685 bool haveStencilBuffer = false;
5687 if (m_framebufferBinding)
5688 haveStencilBuffer = m_framebufferBinding->hasStencilBuffer();
5690 RefPtr<WebGLContextAttributes> attributes = getContextAttributes();
5691 haveStencilBuffer = attributes->stencil();
5693 enableOrDisable(GraphicsContext3D::STENCIL_TEST,
5694 m_stencilEnabled && haveStencilBuffer);
5697 void WebGLRenderingContext::enableOrDisable(GC3Denum capability, bool enable)
5700 m_context->enable(capability);
5702 m_context->disable(capability);
5705 IntSize WebGLRenderingContext::clampedCanvasSize()
5707 return IntSize(clamp(canvas()->width(), 1, m_maxViewportDims[0]),
5708 clamp(canvas()->height(), 1, m_maxViewportDims[1]));
5711 } // namespace WebCore
5713 #endif // ENABLE(WEBGL)