Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(208)

Unified Diff: Source/WebCore/platform/graphics/chromium/LayerTilerChromium.cpp

Issue 7590009: Merge 92255 - Source/WebCore: [Chromium] Use edge-distance method for layer anti-aliasing. (Closed) Base URL: http://svn.webkit.org/repository/webkit/branches/chromium/835/
Patch Set: Created 9 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: Source/WebCore/platform/graphics/chromium/LayerTilerChromium.cpp
===================================================================
--- Source/WebCore/platform/graphics/chromium/LayerTilerChromium.cpp (revision 92714)
+++ Source/WebCore/platform/graphics/chromium/LayerTilerChromium.cpp (working copy)
@@ -84,6 +84,7 @@
reset();
m_tileSize = size;
+ m_tilingData.setMaxTextureSize(max(size.width(), size.height()));
}
LayerTexture* LayerTilerChromium::getSingleTexture()
@@ -189,23 +190,16 @@
IntRect LayerTilerChromium::tileLayerRect(const Tile* tile) const
{
const int index = m_tilingData.tileIndex(tile->i(), tile->j());
- return m_tilingData.tileBoundsWithBorder(index);
+ IntRect layerRect = m_tilingData.tileBoundsWithBorder(index);
+ layerRect.setSize(m_tileSize);
+ return layerRect;
}
-IntRect LayerTilerChromium::tileTexRect(const Tile* tile) const
-{
- const int index = m_tilingData.tileIndex(tile->i(), tile->j());
- return m_tilingData.tileBoundsWithOuterBorder(index);
-}
-
void LayerTilerChromium::invalidateRect(const IntRect& contentRect)
{
if (contentRect.isEmpty() || m_skipsDraw)
return;
- IntSize oldLayerSize(m_tilingData.totalSizeX(), m_tilingData.totalSizeY());
- const IntRect oldLayerRect = IntRect(IntPoint(), oldLayerSize);
-
growLayerToContain(contentRect);
// Dirty rects are always in layer space, as the layer could be repositioned
@@ -222,12 +216,6 @@
IntRect bound = tileLayerRect(tile);
bound.intersect(layerRect);
tile->m_dirtyLayerRect.unite(bound);
-
- // Invalidate old layer area to clear any contents left from
- // previous layer size.
- IntRect oldBound = tileLayerRect(tile);
- oldBound.intersect(oldLayerRect);
- tile->m_dirtyLayerRect.unite(oldBound);
}
}
}
@@ -284,7 +272,6 @@
// Create tiles as needed, expanding a dirty rect to contain all
// the dirty regions currently being drawn.
IntRect dirtyLayerRect;
- IntSize tileSize;
int left, top, right, bottom;
contentRectToTileIndices(contentRect, left, top, right, bottom);
for (int j = top; j <= bottom; ++j) {
@@ -293,19 +280,16 @@
if (!tile)
tile = createTile(i, j);
- IntSize texSize = tileTexRect(tile).size();
- if (!tile->texture()->isValid(texSize, m_textureFormat))
+ if (!tile->texture()->isValid(m_tileSize, m_textureFormat))
tile->m_dirtyLayerRect = tileLayerRect(tile);
- if (!tile->texture()->reserve(texSize, m_textureFormat)) {
+ if (!tile->texture()->reserve(m_tileSize, m_textureFormat)) {
m_skipsDraw = true;
reset();
return;
}
dirtyLayerRect.unite(tile->m_dirtyLayerRect);
-
- tileSize = tileSize.expandedTo(texSize);
}
}
@@ -318,7 +302,7 @@
if (dirtyLayerRect.isEmpty())
return;
- textureUpdater->prepareToUpdate(m_paintRect, tileSize, m_tilingData.borderTexels());
+ textureUpdater->prepareToUpdate(m_paintRect, m_tileSize, m_tilingData.borderTexels());
}
void LayerTilerChromium::updateRect(LayerTextureUpdater* textureUpdater)
@@ -343,8 +327,7 @@
// Calculate page-space rectangle to copy from.
IntRect sourceRect = tileContentRect(tile);
- IntRect texRect = tileTexRect(tile);
- const IntPoint anchor = texRect.location();
+ const IntPoint anchor = sourceRect.location();
sourceRect.intersect(layerRectToContentRect(tile->m_dirtyLayerRect));
// Paint rect not guaranteed to line up on tile boundaries, so
// make sure that sourceRect doesn't extend outside of it.
@@ -394,12 +377,22 @@
if (m_skipsDraw || !m_tiles.size() || contentRect.isEmpty())
return;
+ // Use anti-aliasing programs when border texels are preset and transform
+ // is not an integer translation.
+ bool useAA = (m_tilingData.borderTexels() && !globalTransform.isIntegerTranslation());
+
switch (m_sampledTexelFormat) {
case LayerTextureUpdater::SampledTexelFormatRGBA:
- drawTiles(contentRect, globalTransform, opacity, layerRenderer()->tilerProgram());
+ if (useAA)
+ drawTiles(contentRect, globalTransform, opacity, layerRenderer()->tilerProgramAA(), layerRenderer()->tilerProgramAA()->fragmentShader().fragmentTexTransformLocation(), layerRenderer()->tilerProgramAA()->fragmentShader().edgeLocation());
+ else
+ drawTiles(contentRect, globalTransform, opacity, layerRenderer()->tilerProgram(), -1, -1);
break;
case LayerTextureUpdater::SampledTexelFormatBGRA:
- drawTiles(contentRect, globalTransform, opacity, layerRenderer()->tilerProgramSwizzle());
+ if (useAA)
+ drawTiles(contentRect, globalTransform, opacity, layerRenderer()->tilerProgramSwizzleAA(), layerRenderer()->tilerProgramSwizzleAA()->fragmentShader().fragmentTexTransformLocation(), layerRenderer()->tilerProgramSwizzleAA()->fragmentShader().edgeLocation());
+ else
+ drawTiles(contentRect, globalTransform, opacity, layerRenderer()->tilerProgramSwizzle(), -1, -1);
break;
default:
ASSERT_NOT_REACHED();
@@ -411,17 +404,7 @@
// Grow the tile array to contain this content rect.
IntRect layerRect = contentRectToLayerRect(contentRect);
IntSize rectSize = IntSize(layerRect.maxX(), layerRect.maxY());
- IntSize texSize = m_tileSize;
- // Use rect with border texels as max texture size when tile size
- // has not been specified.
- if (texSize.isEmpty()) {
- texSize = rectSize;
- if (m_tilingData.borderTexels())
- texSize.expand(2, 2);
- }
-
- m_tilingData.setMaxTextureSize(max(texSize.width(), texSize.height()));
IntSize oldLayerSize(m_tilingData.totalSizeX(), m_tilingData.totalSizeY());
IntSize newSize = rectSize.expandedTo(oldLayerSize);
m_tilingData.setTotalSize(newSize.width(), newSize.height());
@@ -457,15 +440,10 @@
}
template <class T>
-void LayerTilerChromium::drawTiles(const IntRect& contentRect, const TransformationMatrix& globalTransform, float opacity, const T* program)
+void LayerTilerChromium::drawTiles(const IntRect& contentRect, const TransformationMatrix& globalTransform, float opacity, const T* program, int fragmentTexTransformLocation, int edgeLocation)
{
- GraphicsContext3D* context = layerRendererContext();
- GLC(context, context->useProgram(program->program()));
- GLC(context, context->uniform1i(program->fragmentShader().samplerLocation(), 0));
- GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE0));
+ TransformationMatrix matrix(layerRenderer()->windowMatrix() * layerRenderer()->projectionMatrix() * globalTransform);
- TransformationMatrix matrix(globalTransform);
-
// We don't care about Z component.
TransformationMatrix matrixXYW =
TransformationMatrix(matrix.m11(), matrix.m12(), 0, matrix.m14(),
@@ -478,44 +456,65 @@
return;
TransformationMatrix inverse = matrixXYW.inverse();
- IntRect bounds(m_layerPosition, IntSize(m_tilingData.totalSizeX(),
- m_tilingData.totalSizeY()));
- // Include outer border texels in bounds.
- bounds.inflate(m_tilingData.borderTexels());
+ GraphicsContext3D* context = layerRendererContext();
+ GLC(context, context->useProgram(program->program()));
+ GLC(context, context->uniform1i(program->fragmentShader().samplerLocation(), 0));
+ GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE0));
- // Map bounds to device space.
- FloatQuad boundsQuad = matrix.mapQuad(FloatQuad(bounds));
+ // Map content rectangle to device space.
+ FloatQuad deviceQuad = matrix.mapQuad(FloatQuad(contentRect));
// Counter-clockwise?
- float sign = isCCW(boundsQuad) ? -1 : 1;
+ float sign = isCCW(deviceQuad) ? -1 : 1;
// Compute outer edges.
- Edge leftEdge = computeEdge(boundsQuad.p4(), boundsQuad.p1(), sign);
- Edge rightEdge = computeEdge(boundsQuad.p2(), boundsQuad.p3(), sign);
- Edge topEdge = computeEdge(boundsQuad.p1(), boundsQuad.p2(), sign);
- Edge bottomEdge = computeEdge(boundsQuad.p3(), boundsQuad.p4(), sign);
+ Edge leftEdge = computeEdge(deviceQuad.p4(), deviceQuad.p1(), sign);
+ Edge rightEdge = computeEdge(deviceQuad.p2(), deviceQuad.p3(), sign);
+ Edge topEdge = computeEdge(deviceQuad.p1(), deviceQuad.p2(), sign);
+ Edge bottomEdge = computeEdge(deviceQuad.p3(), deviceQuad.p4(), sign);
- // Move outer edges to ensure that all partially covered pixels are
- // processed.
- float zDistance = m_tilingData.borderTexels() * 0.5f;
- leftEdge.move(0, 0, zDistance);
- rightEdge.move(0, 0, zDistance);
- topEdge.move(0, 0, zDistance);
- bottomEdge.move(0, 0, zDistance);
+ if (edgeLocation != -1) {
+ // Move outer edges to ensure that all partially covered pixels are
+ // processed.
+ leftEdge.move(0, 0, 0.5f);
+ rightEdge.move(0, 0, 0.5f);
+ topEdge.move(0, 0, 0.5f);
+ bottomEdge.move(0, 0, 0.5f);
- GC3Dint filter = (m_tilingData.borderTexels() && !matrix.isIntegerTranslation()) ? GraphicsContext3D::LINEAR : GraphicsContext3D::NEAREST;
+ float edge[12];
+ edge[0] = leftEdge.x();
+ edge[1] = leftEdge.y();
+ edge[2] = leftEdge.z();
+ edge[3] = topEdge.x();
+ edge[4] = topEdge.y();
+ edge[5] = topEdge.z();
+ edge[6] = rightEdge.x();
+ edge[7] = rightEdge.y();
+ edge[8] = rightEdge.z();
+ edge[9] = bottomEdge.x();
+ edge[10] = bottomEdge.y();
+ edge[11] = bottomEdge.z();
+ GLC(context, context->uniform3fv(edgeLocation, edge, 4));
+ }
Edge prevEdgeY = topEdge;
int left, top, right, bottom;
contentRectToTileIndices(contentRect, left, top, right, bottom);
+ IntRect layerRect = contentRectToLayerRect(contentRect);
for (int j = top; j <= bottom; ++j) {
Edge prevEdgeX = leftEdge;
Edge edgeY = bottomEdge;
if (j < (m_tilingData.numTilesY() - 1)) {
- IntRect tileRect = m_tilingData.tileBounds(m_tilingData.tileIndex(0, j));
+ IntRect tileRect = unionRect(m_tilingData.tileBounds(m_tilingData.tileIndex(0, j)), m_tilingData.tileBounds(m_tilingData.tileIndex(m_tilingData.numTilesX() - 1, j)));
+ tileRect.intersect(layerRect);
+
+ // Skip empty rows.
+ if (tileRect.isEmpty())
+ continue;
+
tileRect.move(m_layerPosition.x(), m_layerPosition.y());
FloatPoint p1(tileRect.maxX(), tileRect.maxY());
@@ -537,27 +536,58 @@
ASSERT(tile->texture()->isReserved());
tile->texture()->bindTexture();
- GLC(context, context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, filter));
- GLC(context, context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, filter));
// Don't use tileContentRect here, as that contains the full
// rect with border texels which shouldn't be drawn.
IntRect tileRect = m_tilingData.tileBounds(m_tilingData.tileIndex(tile->i(), tile->j()));
+ IntRect displayRect = tileRect;
+ tileRect.intersect(layerRect);
+
+ // Keep track of how the top left has moved, so the texture can be
+ // offset the same amount.
+ IntSize displayOffset = tileRect.minXMinYCorner() - displayRect.minXMinYCorner();
+
+ // Skip empty tiles.
+ if (tileRect.isEmpty())
+ continue;
+
tileRect.move(m_layerPosition.x(), m_layerPosition.y());
- IntPoint texOffset = m_tilingData.textureOffset();
- IntRect texRect = tileTexRect(tile);
- float tileWidth = static_cast<float>(texRect.width());
- float tileHeight = static_cast<float>(texRect.height());
- float texTranslateX = (texOffset.x() - tileRect.x()) / tileWidth;
- float texTranslateY = (texOffset.y() - tileRect.y()) / tileHeight;
- float texScaleX = tileRect.width() / tileWidth;
- float texScaleY = tileRect.height() / tileHeight;
+ FloatRect clampRect(tileRect);
+ // Clamp texture coordinates to avoid sampling outside the layer
+ // by deflating the tile region half a texel or half a texel
+ // minus epsilon for one pixel layers. The resulting clamp region
+ // is mapped to the unit square by the vertex shader and mapped
+ // back to normalized texture coordinates by the fragment shader
+ // after being clamped to 0-1 range.
+ const float epsilon = 1 / 1024.0f;
+ float clampX = min(0.5, clampRect.width() / 2.0 - epsilon);
+ float clampY = min(0.5, clampRect.height() / 2.0 - epsilon);
+ clampRect.inflateX(-clampX);
+ clampRect.inflateY(-clampY);
+ FloatSize clampOffset = clampRect.minXMinYCorner() - FloatRect(tileRect).minXMinYCorner();
+
+ FloatPoint texOffset = m_tilingData.textureOffset(tile->i(), tile->j()) + clampOffset + FloatSize(displayOffset);
+ float tileWidth = static_cast<float>(m_tileSize.width());
+ float tileHeight = static_cast<float>(m_tileSize.height());
+
+ // Map clamping rectangle to unit square.
+ float vertexTexTranslateX = -clampRect.x() / clampRect.width();
+ float vertexTexTranslateY = -clampRect.y() / clampRect.height();
+ float vertexTexScaleX = tileRect.width() / clampRect.width();
+ float vertexTexScaleY = tileRect.height() / clampRect.height();
+
+ // Map to normalized texture coordinates.
+ float fragmentTexTranslateX = texOffset.x() / tileWidth;
+ float fragmentTexTranslateY = texOffset.y() / tileHeight;
+ float fragmentTexScaleX = clampRect.width() / tileWidth;
+ float fragmentTexScaleY = clampRect.height() / tileHeight;
+
// OpenGL coordinate system is bottom-up.
// If tile texture is top-down, we need to flip the texture coordinates.
if (m_textureOrientation == LayerTextureUpdater::TopDownOrientation) {
- texTranslateY = 1.0 - texTranslateY;
- texScaleY *= -1.0;
+ fragmentTexTranslateY = 1.0 - fragmentTexTranslateY;
+ fragmentTexScaleY *= -1.0;
}
Edge edgeX = rightEdge;
@@ -585,53 +615,50 @@
// Normalize to tileRect.
quad.scale(1.0f / tileRect.width(), 1.0f / tileRect.height());
- drawTexturedQuad(context, quad, layerRenderer()->projectionMatrix(), matrix, tileRect.width(), tileRect.height(), opacity, texTranslateX, texTranslateY, texScaleX, texScaleY, program);
+ if (fragmentTexTransformLocation == -1) {
+ // Move fragment shader transform to vertex shader. We can do
+ // this while still producing correct results as
+ // fragmentTexTransformLocation should always be non-negative
+ // when tiles are transformed in a way that could result in
+ // sampling outside the layer.
+ vertexTexScaleX *= fragmentTexScaleX;
+ vertexTexScaleY *= fragmentTexScaleY;
+ vertexTexTranslateX *= fragmentTexScaleX;
+ vertexTexTranslateY *= fragmentTexScaleY;
+ vertexTexTranslateX += fragmentTexTranslateX;
+ vertexTexTranslateY += fragmentTexTranslateY;
+ } else
+ GLC(context, context->uniform4f(fragmentTexTransformLocation, fragmentTexTranslateX, fragmentTexTranslateY, fragmentTexScaleX, fragmentTexScaleY));
+ GLC(context, context->uniform4f(program->vertexShader().vertexTexTransformLocation(), vertexTexTranslateX, vertexTexTranslateY, vertexTexScaleX, vertexTexScaleY));
+
+ float point[8];
+ point[0] = quad.p1().x();
+ point[1] = quad.p1().y();
+ point[2] = quad.p2().x();
+ point[3] = quad.p2().y();
+ point[4] = quad.p3().x();
+ point[5] = quad.p3().y();
+ point[6] = quad.p4().x();
+ point[7] = quad.p4().y();
+ GLC(context, context->uniform2fv(program->vertexShader().pointLocation(), point, 4));
+
+ LayerChromium::drawTexturedQuad(context, layerRenderer()->projectionMatrix(), globalTransform,
+ tileRect.width(), tileRect.height(), opacity,
+ program->vertexShader().matrixLocation(),
+ program->fragmentShader().alphaLocation());
+
prevEdgeX = edgeX;
+ // Reverse direction.
+ prevEdgeX.scale(-1, -1, -1);
}
prevEdgeY = edgeY;
+ // Reverse direction.
+ prevEdgeY.scale(-1, -1, -1);
}
}
-template <class T>
-void LayerTilerChromium::drawTexturedQuad(GraphicsContext3D* context, const FloatQuad& quad, const TransformationMatrix& projectionMatrix, const TransformationMatrix& drawMatrix,
- float width, float height, float opacity,
- float texTranslateX, float texTranslateY,
- float texScaleX, float texScaleY,
- const T* program)
-{
- static float glMatrix[16];
-
- TransformationMatrix renderMatrix = drawMatrix;
-
- // Apply a scaling factor to size the quad from 1x1 to its intended size.
- renderMatrix.scale3d(width, height, 1);
-
- // Apply the projection matrix before sending the transform over to the shader.
- LayerChromium::toGLMatrix(&glMatrix[0], projectionMatrix * renderMatrix);
-
- GLC(context, context->uniformMatrix4fv(program->vertexShader().matrixLocation(), false, &glMatrix[0], 1));
-
- GLC(context, context->uniform1f(program->fragmentShader().alphaLocation(), opacity));
-
- GLC(context, context->uniform4f(program->vertexShader().texTransformLocation(),
- texTranslateX, texTranslateY, texScaleX, texScaleY));
-
- float point[8];
- point[0] = quad.p1().x();
- point[1] = quad.p1().y();
- point[2] = quad.p2().x();
- point[3] = quad.p2().y();
- point[4] = quad.p3().x();
- point[5] = quad.p3().y();
- point[6] = quad.p4().x();
- point[7] = quad.p4().y();
- GLC(context, context->uniform2fv(program->vertexShader().pointLocation(), point, 4));
-
- GLC(context, context->drawElements(GraphicsContext3D::TRIANGLES, 6, GraphicsContext3D::UNSIGNED_SHORT, 0));
-}
-
} // namespace WebCore
#endif // USE(ACCELERATED_COMPOSITING)

Powered by Google App Engine
This is Rietveld 408576698