summaryrefslogtreecommitdiffstats
path: root/Source/WebCore/html/canvas
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebCore/html/canvas')
-rw-r--r--Source/WebCore/html/canvas/CanvasRenderingContext2D.cpp2
-rw-r--r--Source/WebCore/html/canvas/WebGLContextAttributes.cpp10
-rw-r--r--Source/WebCore/html/canvas/WebGLContextAttributes.h5
-rw-r--r--Source/WebCore/html/canvas/WebGLContextAttributes.idl1
-rw-r--r--Source/WebCore/html/canvas/WebGLRenderingContext.cpp122
-rw-r--r--Source/WebCore/html/canvas/WebGLRenderingContext.h14
6 files changed, 145 insertions, 9 deletions
diff --git a/Source/WebCore/html/canvas/CanvasRenderingContext2D.cpp b/Source/WebCore/html/canvas/CanvasRenderingContext2D.cpp
index a549782..f5ff078 100644
--- a/Source/WebCore/html/canvas/CanvasRenderingContext2D.cpp
+++ b/Source/WebCore/html/canvas/CanvasRenderingContext2D.cpp
@@ -146,7 +146,7 @@ CanvasRenderingContext2D::~CanvasRenderingContext2D()
bool CanvasRenderingContext2D::isAccelerated() const
{
#if USE(IOSURFACE_CANVAS_BACKING_STORE)
- return true;
+ return canvas()->document()->page()->settings()->canvasUsesAcceleratedDrawing();
#elif ENABLE(ACCELERATED_2D_CANVAS)
return m_context3D;
#else
diff --git a/Source/WebCore/html/canvas/WebGLContextAttributes.cpp b/Source/WebCore/html/canvas/WebGLContextAttributes.cpp
index 6a47ea9..e36e04e 100644
--- a/Source/WebCore/html/canvas/WebGLContextAttributes.cpp
+++ b/Source/WebCore/html/canvas/WebGLContextAttributes.cpp
@@ -107,6 +107,16 @@ void WebGLContextAttributes::setPremultipliedAlpha(bool premultipliedAlpha)
m_attrs.premultipliedAlpha = premultipliedAlpha;
}
+bool WebGLContextAttributes::preserveDrawingBuffer() const
+{
+ return m_attrs.preserveDrawingBuffer;
+}
+
+void WebGLContextAttributes::setPreserveDrawingBuffer(bool preserveDrawingBuffer)
+{
+ m_attrs.preserveDrawingBuffer = preserveDrawingBuffer;
+}
+
GraphicsContext3D::Attributes WebGLContextAttributes::attributes() const
{
return m_attrs;
diff --git a/Source/WebCore/html/canvas/WebGLContextAttributes.h b/Source/WebCore/html/canvas/WebGLContextAttributes.h
index a108605..5391a2b 100644
--- a/Source/WebCore/html/canvas/WebGLContextAttributes.h
+++ b/Source/WebCore/html/canvas/WebGLContextAttributes.h
@@ -65,6 +65,11 @@ class WebGLContextAttributes : public CanvasContextAttributes {
bool premultipliedAlpha() const;
void setPremultipliedAlpha(bool premultipliedAlpha);
+ // Whether or not to preserve the drawing buffer after presentation to the
+ // screen; default=false
+ bool preserveDrawingBuffer() const;
+ void setPreserveDrawingBuffer(bool);
+
// Fetches a copy of the attributes stored in this object in a
// form that can be used to initialize a GraphicsContext3D.
GraphicsContext3D::Attributes attributes() const;
diff --git a/Source/WebCore/html/canvas/WebGLContextAttributes.idl b/Source/WebCore/html/canvas/WebGLContextAttributes.idl
index 0fa0c2c..56da1c6 100644
--- a/Source/WebCore/html/canvas/WebGLContextAttributes.idl
+++ b/Source/WebCore/html/canvas/WebGLContextAttributes.idl
@@ -34,5 +34,6 @@ module html {
attribute boolean stencil;
attribute boolean antialias;
attribute boolean premultipliedAlpha;
+ attribute boolean preserveDrawingBuffer;
};
}
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)
diff --git a/Source/WebCore/html/canvas/WebGLRenderingContext.h b/Source/WebCore/html/canvas/WebGLRenderingContext.h
index 13145c8..f716efb 100644
--- a/Source/WebCore/html/canvas/WebGLRenderingContext.h
+++ b/Source/WebCore/html/canvas/WebGLRenderingContext.h
@@ -285,7 +285,9 @@ public:
void reshape(int width, int height);
+ void markLayerComposited();
virtual void paintRenderingResultsToCanvas();
+ virtual PassRefPtr<ImageData> paintRenderingResultsToImageData();
void removeObject(WebGLObject*);
@@ -443,6 +445,13 @@ public:
bool m_contextLost;
GraphicsContext3D::Attributes m_attributes;
+ bool m_layerCleared;
+ GC3Dfloat m_clearColor[4];
+ bool m_scissorEnabled;
+ GC3Dfloat m_clearDepth;
+ GC3Dint m_clearStencil;
+ GC3Dboolean m_colorMask[4];
+
long m_stencilBits;
GC3Duint m_stencilMask, m_stencilMaskBack;
GC3Dint m_stencilFuncRef, m_stencilFuncRefBack; // Note that these are the user specified values, not the internal clamped value.
@@ -469,6 +478,11 @@ public:
WebGLGetInfo getWebGLFloatArrayParameter(GC3Denum);
WebGLGetInfo getWebGLIntArrayParameter(GC3Denum);
+ // Clear the backbuffer if it was composited since the last operation.
+ // clearMask is set to the bitfield of any clear that would happen anyway at this time
+ // and the function returns true if that clear is now unnecessary.
+ bool clearIfComposited(GC3Dbitfield clearMask = 0);
+
void texImage2DBase(GC3Denum target, GC3Dint level, GC3Denum internalformat,
GC3Dsizei width, GC3Dsizei height, GC3Dint border,
GC3Denum format, GC3Denum type, void* pixels, ExceptionCode&);