summaryrefslogtreecommitdiffstats
path: root/Source/WebCore/html/canvas/WebGLRenderingContext.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebCore/html/canvas/WebGLRenderingContext.cpp')
-rw-r--r--Source/WebCore/html/canvas/WebGLRenderingContext.cpp122
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)