diff options
Diffstat (limited to 'Source/WebCore/html/canvas/WebGLRenderingContext.cpp')
-rw-r--r-- | Source/WebCore/html/canvas/WebGLRenderingContext.cpp | 122 |
1 files changed, 114 insertions, 8 deletions
diff --git a/Source/WebCore/html/canvas/WebGLRenderingContext.cpp b/Source/WebCore/html/canvas/WebGLRenderingContext.cpp index cc7a23b..aa40a64 100644 --- a/Source/WebCore/html/canvas/WebGLRenderingContext.cpp +++ b/Source/WebCore/html/canvas/WebGLRenderingContext.cpp @@ -412,6 +412,13 @@ void WebGLRenderingContext::initializeNewContext() m_stencilFuncRefBack = 0; m_stencilFuncMask = 0xFFFFFFFF; m_stencilFuncMaskBack = 0xFFFFFFFF; + m_layerCleared = false; + + m_clearColor[0] = m_clearColor[1] = m_clearColor[2] = m_clearColor[3] = 0; + m_scissorEnabled = false; + m_clearDepth = 1; + m_clearStencil = 0; + m_colorMask[0] = m_colorMask[1] = m_colorMask[2] = m_colorMask[3] = true; GC3Dint numCombinedTextureImageUnits = 0; m_context->getIntegerv(GraphicsContext3D::MAX_COMBINED_TEXTURE_IMAGE_UNITS, &numCombinedTextureImageUnits); @@ -472,6 +479,10 @@ WebGLRenderingContext::~WebGLRenderingContext() void WebGLRenderingContext::markContextChanged() { + if (m_framebufferBinding) + return; + m_context->markContextChanged(); + m_layerCleared = false; #if USE(ACCELERATED_COMPOSITING) RenderBox* renderBox = canvas()->renderBox(); if (renderBox && renderBox->hasLayer() && renderBox->layer()->hasAcceleratedCompositing()) @@ -486,15 +497,81 @@ void WebGLRenderingContext::markContextChanged() m_markedCanvasDirty = true; } +bool WebGLRenderingContext::clearIfComposited(GC3Dbitfield mask) +{ + if (isContextLost()) + return false; + + RefPtr<WebGLContextAttributes> contextAttributes = getContextAttributes(); + + if (!m_context->layerComposited() || m_layerCleared + || m_attributes.preserveDrawingBuffer || m_framebufferBinding) + return false; + + // Determine if it's possible to combine the clear the user asked for and this clear. + bool combinedClear = mask && !m_scissorEnabled; + + m_context->disable(GraphicsContext3D::SCISSOR_TEST); + if (combinedClear && (mask & GraphicsContext3D::COLOR_BUFFER_BIT)) + m_context->clearColor(m_colorMask[0] ? m_clearColor[0] : 0, + m_colorMask[1] ? m_clearColor[1] : 0, + m_colorMask[2] ? m_clearColor[2] : 0, + m_colorMask[3] ? m_clearColor[3] : 0); + else + m_context->clearColor(0, 0, 0, 0); + m_context->colorMask(true, true, true, true); + if (contextAttributes->depth() && (!combinedClear || !(mask & GraphicsContext3D::DEPTH_BUFFER_BIT))) + m_context->clearDepth(1.0f); + if (contextAttributes->stencil() && (!combinedClear || !(mask & GraphicsContext3D::STENCIL_BUFFER_BIT))) + m_context->clearStencil(0); + GC3Dbitfield clearMask = GraphicsContext3D::COLOR_BUFFER_BIT; + if (contextAttributes->depth()) + clearMask |= GraphicsContext3D::DEPTH_BUFFER_BIT; + if (contextAttributes->stencil()) + clearMask |= GraphicsContext3D::STENCIL_BUFFER_BIT; + m_context->clear(clearMask); + + // Restore the state that the context set. + if (m_scissorEnabled) + m_context->enable(GraphicsContext3D::SCISSOR_TEST); + m_context->clearColor(m_clearColor[0], m_clearColor[1], + m_clearColor[2], m_clearColor[3]); + m_context->colorMask(m_colorMask[0], m_colorMask[1], + m_colorMask[2], m_colorMask[3]); + m_context->clearDepth(m_clearDepth); + m_context->clearStencil(m_clearStencil); + m_layerCleared = true; + + return combinedClear; +} + +void WebGLRenderingContext::markLayerComposited() +{ + m_context->markLayerComposited(); +} + void WebGLRenderingContext::paintRenderingResultsToCanvas() { - if (!m_markedCanvasDirty) + // Until the canvas is written to by the application, the clear that + // happened after it was composited should be ignored by the compositor. + if (m_context->layerComposited() && !m_attributes.preserveDrawingBuffer) + canvas()->makePresentationCopy(); + else + canvas()->clearPresentationCopy(); + clearIfComposited(); + if (!m_markedCanvasDirty && !m_layerCleared) return; canvas()->clearCopiedImage(); m_markedCanvasDirty = false; m_context->paintRenderingResultsToCanvas(this); } +PassRefPtr<ImageData> WebGLRenderingContext::paintRenderingResultsToImageData() +{ + clearIfComposited(); + return m_context->paintRenderingResultsToImageData(); +} + bool WebGLRenderingContext::paintsIntoCanvasBuffer() const { return m_context->paintsIntoCanvasBuffer(); @@ -885,7 +962,8 @@ void WebGLRenderingContext::clear(GC3Dbitfield mask) m_context->synthesizeGLError(GraphicsContext3D::INVALID_FRAMEBUFFER_OPERATION); return; } - m_context->clear(mask); + if (!clearIfComposited(mask)) + m_context->clear(mask); cleanupAfterGraphicsCall(true); } @@ -901,6 +979,10 @@ void WebGLRenderingContext::clearColor(GC3Dfloat r, GC3Dfloat g, GC3Dfloat b, GC b = 0; if (isnan(a)) a = 1; + m_clearColor[0] = r; + m_clearColor[1] = g; + m_clearColor[2] = b; + m_clearColor[3] = a; m_context->clearColor(r, g, b, a); cleanupAfterGraphicsCall(false); } @@ -909,6 +991,7 @@ void WebGLRenderingContext::clearDepth(GC3Dfloat depth) { if (isContextLost()) return; + m_clearDepth = depth; m_context->clearDepth(depth); cleanupAfterGraphicsCall(false); } @@ -917,6 +1000,7 @@ void WebGLRenderingContext::clearStencil(GC3Dint s) { if (isContextLost()) return; + m_clearStencil = s; m_context->clearStencil(s); cleanupAfterGraphicsCall(false); } @@ -925,6 +1009,10 @@ void WebGLRenderingContext::colorMask(GC3Dboolean red, GC3Dboolean green, GC3Dbo { if (isContextLost()) return; + m_colorMask[0] = red; + m_colorMask[1] = green; + m_colorMask[2] = blue; + m_colorMask[3] = alpha; m_context->colorMask(red, green, blue, alpha); cleanupAfterGraphicsCall(false); } @@ -959,6 +1047,7 @@ void WebGLRenderingContext::copyTexImage2D(GC3Denum target, GC3Dint level, GC3De m_context->synthesizeGLError(GraphicsContext3D::INVALID_FRAMEBUFFER_OPERATION); return; } + clearIfComposited(); if (isResourceSafe()) m_context->copyTexImage2D(target, level, internalformat, x, y, width, height, border); else { @@ -1002,6 +1091,7 @@ void WebGLRenderingContext::copyTexSubImage2D(GC3Denum target, GC3Dint level, GC m_context->synthesizeGLError(GraphicsContext3D::INVALID_FRAMEBUFFER_OPERATION); return; } + clearIfComposited(); if (isResourceSafe()) m_context->copyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height); else { @@ -1234,6 +1324,8 @@ void WebGLRenderingContext::disable(GC3Denum cap) { if (isContextLost() || !validateCapability(cap)) return; + if (cap == GraphicsContext3D::SCISSOR_TEST) + m_scissorEnabled = false; m_context->disable(cap); cleanupAfterGraphicsCall(false); } @@ -1479,6 +1571,8 @@ void WebGLRenderingContext::drawArrays(GC3Denum mode, GC3Dint first, GC3Dsizei c return; } + clearIfComposited(); + bool vertexAttrib0Simulated = false; if (!isGLES2Compliant()) vertexAttrib0Simulated = simulateVertexAttrib0(first + count - 1); @@ -1550,6 +1644,7 @@ void WebGLRenderingContext::drawElements(GC3Denum mode, GC3Dsizei count, GC3Denu m_context->synthesizeGLError(GraphicsContext3D::INVALID_FRAMEBUFFER_OPERATION); return; } + clearIfComposited(); bool vertexAttrib0Simulated = false; if (!isGLES2Compliant()) { @@ -1571,6 +1666,8 @@ void WebGLRenderingContext::enable(GC3Denum cap) { if (isContextLost() || !validateCapability(cap)) return; + if (cap == GraphicsContext3D::SCISSOR_TEST) + m_scissorEnabled = true; m_context->enable(cap); cleanupAfterGraphicsCall(false); } @@ -1597,7 +1694,7 @@ void WebGLRenderingContext::finish() if (isContextLost()) return; m_context->finish(); - cleanupAfterGraphicsCall(true); + cleanupAfterGraphicsCall(false); } void WebGLRenderingContext::flush() @@ -1605,7 +1702,7 @@ void WebGLRenderingContext::flush() if (isContextLost()) return; m_context->flush(); - cleanupAfterGraphicsCall(true); + cleanupAfterGraphicsCall(false); } void WebGLRenderingContext::framebufferRenderbuffer(GC3Denum target, GC3Denum attachment, GC3Denum renderbuffertarget, WebGLRenderbuffer* buffer, ExceptionCode& ec) @@ -2752,6 +2849,7 @@ void WebGLRenderingContext::readPixels(GC3Dint x, GC3Dint y, GC3Dsizei width, GC m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION); return; } + clearIfComposited(); void* data = pixels->baseAddress(); m_context->readPixels(x, y, width, height, format, type, data); #if OS(DARWIN) @@ -3062,8 +3160,12 @@ void WebGLRenderingContext::texImage2D(GC3Denum target, GC3Dint level, GC3Denum return; } checkOrigin(canvas); - texImage2DImpl(target, level, internalformat, format, type, canvas->copiedImage(), - m_unpackFlipY, m_unpackPremultiplyAlpha, ec); + RefPtr<ImageData> imageData = canvas->getImageData(); + if (imageData) + texImage2D(target, level, internalformat, format, type, imageData.get(), ec); + else + texImage2DImpl(target, level, internalformat, format, type, canvas->copiedImage(), + m_unpackFlipY, m_unpackPremultiplyAlpha, ec); } #if ENABLE(VIDEO) @@ -3252,8 +3354,12 @@ void WebGLRenderingContext::texSubImage2D(GC3Denum target, GC3Dint level, GC3Din return; } checkOrigin(canvas); - texSubImage2DImpl(target, level, xoffset, yoffset, format, type, canvas->copiedImage(), - m_unpackFlipY, m_unpackPremultiplyAlpha, ec); + RefPtr<ImageData> imageData = canvas->getImageData(); + if (imageData) + texSubImage2D(target, level, xoffset, yoffset, format, type, imageData.get(), ec); + else + texSubImage2DImpl(target, level, xoffset, yoffset, format, type, canvas->copiedImage(), + m_unpackFlipY, m_unpackPremultiplyAlpha, ec); } #if ENABLE(VIDEO) |