Modified: trunk/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp (101907 => 101908)
--- trunk/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp 2011-12-03 06:06:56 UTC (rev 101907)
+++ trunk/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp 2011-12-03 06:14:08 UTC (rev 101908)
@@ -53,6 +53,7 @@
#include "TrackingTextureAllocator.h"
#include "TreeSynchronizer.h"
#include "WebGLLayerChromium.h"
+#include "cc/CCDamageTracker.h"
#include "cc/CCLayerImpl.h"
#include "cc/CCLayerTreeHostCommon.h"
#include "cc/CCProxy.h"
@@ -107,6 +108,21 @@
return screen;
}
+static TransformationMatrix computeScreenSpaceTransformForSurface(CCLayerImpl* renderSurfaceLayer)
+{
+ // The layer's screen space transform can be written as:
+ // layerScreenSpaceTransform = surfaceScreenSpaceTransform * layerOriginTransform
+ // So, to compute the surface screen space, we can do:
+ // surfaceScreenSpaceTransform = layerScreenSpaceTransform * inverse(layerOriginTransform)
+
+ TransformationMatrix layerOriginTransform = renderSurfaceLayer->drawTransform();
+ layerOriginTransform.translate(-0.5 * renderSurfaceLayer->bounds().width(), -0.5 * renderSurfaceLayer->bounds().height());
+ TransformationMatrix surfaceScreenSpaceTransform = renderSurfaceLayer->screenSpaceTransform();
+ surfaceScreenSpaceTransform.multiply(layerOriginTransform.inverse());
+
+ return surfaceScreenSpaceTransform;
+}
+
#if USE(SKIA)
bool contextSupportsAcceleratedPainting(GraphicsContext3D* context)
{
@@ -191,9 +207,12 @@
if (m_capabilities.contextHasCachedFrontBuffer)
extensions->ensureEnabled("GL_CHROMIUM_front_buffer_cached");
- m_capabilities.usingPostSubBuffer = extensions->supports("GL_CHROMIUM_post_sub_buffer");
- if (m_capabilities.usingPostSubBuffer)
+ m_capabilities.usingPartialSwap = extensions->supports("GL_CHROMIUM_post_sub_buffer");
+ if (m_capabilities.usingPartialSwap)
extensions->ensureEnabled("GL_CHROMIUM_post_sub_buffer");
+ // FIXME: eventually we would like to have usingPartialSwap enabled by default,
+ // whenever it is supported. For now, we force it off.
+ m_capabilities.usingPartialSwap = false;
m_capabilities.usingMapSub = extensions->supports("GL_CHROMIUM_map_sub");
if (m_capabilities.usingMapSub)
@@ -317,10 +336,30 @@
copyOffscreenTextureToDisplay();
}
+void LayerRendererChromium::trackDamageForAllSurfaces(CCLayerImpl* rootDrawLayer, const CCLayerList& renderSurfaceLayerList)
+{
+ // For now, we use damage tracking to compute a global scissor. To do this, we must
+ // compute all damage tracking before drawing anything, so that we know the root
+ // damage rect. The root damage rect is then used to scissor each surface.
+
+ ASSERT(m_capabilities.usingPartialSwap);
+
+ for (int surfaceIndex = renderSurfaceLayerList.size() - 1; surfaceIndex >= 0 ; --surfaceIndex) {
+ CCLayerImpl* renderSurfaceLayer = renderSurfaceLayerList[surfaceIndex].get();
+ CCRenderSurface* renderSurface = renderSurfaceLayer->renderSurface();
+ ASSERT(renderSurface);
+ renderSurface->damageTracker()->updateDamageRectForNextFrame(renderSurface->layerList(), renderSurfaceLayer->id(), renderSurfaceLayer->maskLayer());
+ }
+}
+
void LayerRendererChromium::drawLayersOntoRenderSurfaces(CCLayerImpl* rootDrawLayer, const CCLayerList& renderSurfaceLayerList)
{
TRACE_EVENT("LayerRendererChromium::drawLayersOntoRenderSurfaces", this, 0);
+ if (m_capabilities.usingPartialSwap)
+ trackDamageForAllSurfaces(rootDrawLayer, renderSurfaceLayerList);
+ m_rootDamageRect = rootDrawLayer->renderSurface()->damageTracker()->currentDamageRect();
+
// Update the contents of the render surfaces. We traverse the render surfaces
// from back to front to guarantee that nested render surfaces get rendered in
// the correct order.
@@ -332,16 +371,31 @@
if (useRenderSurface(renderSurface)) {
+ FloatRect surfaceDamageRect;
+ if (m_capabilities.usingPartialSwap) {
+ // For now, we conservatively use the root damage as the damage for all
+ // surfaces, except perspective transforms.
+ TransformationMatrix screenSpaceTransform = computeScreenSpaceTransformForSurface(renderSurfaceLayer);
+ if (screenSpaceTransform.hasPerspective()) {
+ // Perspective projections do not play nice with mapRect of inverse transforms.
+ // In this uncommon case, its simpler to just redraw the entire surface.
+ surfaceDamageRect = renderSurface->contentRect();
+ } else {
+ TransformationMatrix inverseScreenSpaceTransform = screenSpaceTransform.inverse();
+ surfaceDamageRect = inverseScreenSpaceTransform.mapRect(m_rootDamageRect);
+ }
+ }
+
if (renderSurfaceLayer != rootDrawLayer) {
- GLC(m_context.get(), m_context->disable(GraphicsContext3D::SCISSOR_TEST));
+ if (m_capabilities.usingPartialSwap)
+ setScissorToRect(enclosingIntRect(surfaceDamageRect));
GLC(m_context.get(), m_context->clearColor(0, 0, 0, 0));
GLC(m_context.get(), m_context->clear(GraphicsContext3D::COLOR_BUFFER_BIT));
- GLC(m_context.get(), m_context->enable(GraphicsContext3D::SCISSOR_TEST));
}
const CCLayerList& layerList = renderSurface->layerList();
for (unsigned layerIndex = 0; layerIndex < layerList.size(); ++layerIndex)
- drawLayer(layerList[layerIndex].get(), renderSurface);
+ drawLayer(layerList[layerIndex].get(), renderSurface, surfaceDamageRect);
}
}
@@ -392,20 +446,20 @@
// Bind the common vertex attributes used for drawing all the layers.
m_sharedGeometry->prepareForDraw();
- GLC(m_context.get(), m_context->disable(GraphicsContext3D::SCISSOR_TEST));
GLC(m_context.get(), m_context->disable(GraphicsContext3D::DEPTH_TEST));
GLC(m_context.get(), m_context->disable(GraphicsContext3D::CULL_FACE));
useRenderSurface(m_defaultRenderSurface);
// Clear to blue to make it easier to spot unrendered regions.
+ if (m_capabilities.usingPartialSwap)
+ setScissorToRect(enclosingIntRect(m_rootDamageRect));
m_context->clearColor(0, 0, 1, 1);
m_context->colorMask(true, true, true, true);
m_context->clear(GraphicsContext3D::COLOR_BUFFER_BIT);
GLC(m_context.get(), m_context->enable(GraphicsContext3D::BLEND));
GLC(m_context.get(), m_context->blendFunc(GraphicsContext3D::ONE, GraphicsContext3D::ONE_MINUS_SRC_ALPHA));
- GLC(m_context.get(), m_context->enable(GraphicsContext3D::SCISSOR_TEST));
drawLayersOntoRenderSurfaces(rootDrawLayer, renderSurfaceLayerList);
@@ -487,9 +541,17 @@
TRACE_EVENT("LayerRendererChromium::swapBuffers", this, 0);
// We're done! Time to swapbuffers!
- // Note that currently this has the same effect as swapBuffers; we should
- // consider exposing a different entry point on GraphicsContext3D.
- m_context->prepareTexture();
+ if (m_capabilities.usingPartialSwap) {
+ // If supported, we can save significant bandwidth by only swapping the damaged/scissored region (clamped to the viewport)
+ IntRect subBuffer = enclosingIntRect(m_rootDamageRect);
+ subBuffer.intersect(IntRect(IntPoint::zero(), viewportSize()));
+ Extensions3DChromium* extensions3DChromium = static_cast<Extensions3DChromium*>(m_context->getExtensions());
+ int flippedYPosOfRectBottom = viewportHeight() - subBuffer.y() - subBuffer.height();
+ extensions3DChromium->postSubBufferCHROMIUM(subBuffer.x(), flippedYPosOfRectBottom, subBuffer.width(), subBuffer.height());
+ } else
+ // Note that currently this has the same effect as swapBuffers; we should
+ // consider exposing a different entry point on GraphicsContext3D.
+ m_context->prepareTexture();
m_headsUpDisplay->onSwapBuffers();
}
@@ -582,10 +644,10 @@
return true;
}
-void LayerRendererChromium::drawLayer(CCLayerImpl* layer, CCRenderSurface* targetSurface)
+void LayerRendererChromium::drawLayer(CCLayerImpl* layer, CCRenderSurface* targetSurface, const FloatRect& surfaceDamageRect)
{
if (CCLayerTreeHostCommon::renderSurfaceContributesToTarget<CCLayerImpl>(layer, targetSurface->owningLayerId())) {
- layer->renderSurface()->draw(this, layer->getDrawRect());
+ layer->renderSurface()->draw(this, surfaceDamageRect);
layer->renderSurface()->releaseContentsTexture();
return;
}
@@ -593,7 +655,13 @@
if (layer->visibleLayerRect().isEmpty())
return;
- if (layer->usesLayerClipping())
+ if (layer->usesLayerClipping() && m_capabilities.usingPartialSwap) {
+ FloatRect clipAndDamageRect(layer->clipRect());
+ clipAndDamageRect.intersect(surfaceDamageRect);
+ setScissorToRect(enclosingIntRect(clipAndDamageRect));
+ } else if (m_capabilities.usingPartialSwap)
+ setScissorToRect(enclosingIntRect(surfaceDamageRect));
+ else if (layer->usesLayerClipping())
setScissorToRect(layer->clipRect());
else
GLC(m_context.get(), m_context->disable(GraphicsContext3D::SCISSOR_TEST));
Modified: trunk/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.h (101907 => 101908)
--- trunk/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.h 2011-12-03 06:06:56 UTC (rev 101907)
+++ trunk/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.h 2011-12-03 06:14:08 UTC (rev 101908)
@@ -165,8 +165,10 @@
void drawLayersInternal();
void drawLayersOntoRenderSurfaces(CCLayerImpl* rootDrawLayer, const CCLayerList& renderSurfaceLayerList);
- void drawLayer(CCLayerImpl*, CCRenderSurface*);
+ void drawLayer(CCLayerImpl*, CCRenderSurface*, const FloatRect&);
+ void trackDamageForAllSurfaces(CCLayerImpl* rootDrawLayer, const CCLayerList& renderSurfaceLayerList);
+
ManagedTexture* getOffscreenLayerTexture();
void copyOffscreenTextureToDisplay();
@@ -243,6 +245,8 @@
FloatQuad m_sharedGeometryQuad;
bool m_isViewportChanged;
+
+ FloatRect m_rootDamageRect;
};
// Setting DEBUG_GL_CALLS to 1 will call glGetError() after almost every GL
Modified: trunk/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHost.h (101907 => 101908)
--- trunk/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHost.h 2011-12-03 06:06:56 UTC (rev 101907)
+++ trunk/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHost.h 2011-12-03 06:14:08 UTC (rev 101908)
@@ -73,14 +73,12 @@
, compositeOffscreen(false)
, showFPSCounter(false)
, showPlatformLayerTree(false)
- , useDamageTracker(false)
, refreshRate(0) { }
bool acceleratePainting;
bool compositeOffscreen;
bool showFPSCounter;
bool showPlatformLayerTree;
- bool useDamageTracker;
double refreshRate;
};
@@ -89,7 +87,7 @@
LayerRendererCapabilities()
: bestTextureFormat(0)
, contextHasCachedFrontBuffer(false)
- , usingPostSubBuffer(false)
+ , usingPartialSwap(false)
, usingMapSub(false)
, usingAcceleratedPainting(false)
, usingSetVisibility(false)
@@ -98,7 +96,7 @@
GC3Denum bestTextureFormat;
bool contextHasCachedFrontBuffer;
- bool usingPostSubBuffer;
+ bool usingPartialSwap;
bool usingMapSub;
bool usingAcceleratedPainting;
bool usingSetVisibility;
Modified: trunk/Source/WebCore/platform/graphics/chromium/cc/CCRenderSurface.cpp (101907 => 101908)
--- trunk/Source/WebCore/platform/graphics/chromium/cc/CCRenderSurface.cpp 2011-12-03 06:06:56 UTC (rev 101907)
+++ trunk/Source/WebCore/platform/graphics/chromium/cc/CCRenderSurface.cpp 2011-12-03 06:14:08 UTC (rev 101908)
@@ -101,7 +101,7 @@
m_contentsTexture->unreserve();
}
-void CCRenderSurface::draw(LayerRendererChromium* layerRenderer, const IntRect&)
+void CCRenderSurface::draw(LayerRendererChromium* layerRenderer, const FloatRect& surfaceDamageRect)
{
if (m_skipsDraw || !m_contentsTexture)
return;
@@ -115,7 +115,13 @@
if (!m_maskLayer && m_owningLayer->replicaLayer())
replicaMaskLayer = m_owningLayer->replicaLayer()->maskLayer();
- if (m_owningLayer->parent() && m_owningLayer->parent()->usesLayerClipping())
+ if (m_owningLayer->parent() && m_owningLayer->parent()->usesLayerClipping() && layerRenderer->capabilities().usingPartialSwap) {
+ FloatRect clipAndDamageRect = m_clipRect;
+ clipAndDamageRect.intersect(surfaceDamageRect);
+ layerRenderer->setScissorToRect(enclosingIntRect(clipAndDamageRect));
+ } else if (layerRenderer->capabilities().usingPartialSwap)
+ layerRenderer->setScissorToRect(enclosingIntRect(surfaceDamageRect));
+ else if (m_owningLayer->parent() && m_owningLayer->parent()->usesLayerClipping())
layerRenderer->setScissorToRect(m_clipRect);
else
GLC(layerRenderer->context(), layerRenderer->context()->disable(GraphicsContext3D::SCISSOR_TEST));