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

Unified Diff: cc/gl_renderer.cc

Issue 12393053: Re-land: cc: Added antialiasing support for solid color layers (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: setupQuadForAntialiasing modifies localQuad only if useAA is true Created 7 years, 10 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: cc/gl_renderer.cc
diff --git a/cc/gl_renderer.cc b/cc/gl_renderer.cc
index a7ae9b1e1dfc09a6c8c09c4deea981675b6b65b7..0a0c14085f15ee1622b1a031497efbcfa1640dbf 100644
--- a/cc/gl_renderer.cc
+++ b/cc/gl_renderer.cc
@@ -722,20 +722,156 @@ void GLRenderer::drawRenderPassQuad(DrawingFrame& frame, const RenderPassDrawQua
m_context->flush();
}
+struct SolidColorProgramUniforms {
+ unsigned program;
+ unsigned matrixLocation;
+ unsigned colorLocation;
+ unsigned pointLocation;
+ unsigned texScaleLocation;
+ unsigned edgeLocation;
+};
+
+template<class T>
+static void solidColorUniformLocation(T program, SolidColorProgramUniforms& uniforms)
+{
+ uniforms.program = program->program();
+ uniforms.matrixLocation = program->vertexShader().matrixLocation();
+ uniforms.colorLocation = program->fragmentShader().colorLocation();
+ uniforms.pointLocation = program->vertexShader().pointLocation();
+ uniforms.texScaleLocation = program->vertexShader().texScaleLocation();
+ uniforms.edgeLocation = program->fragmentShader().edgeLocation();
+}
+
+bool GLRenderer::setupQuadForAntialiasing(const gfx::Transform& deviceTransform, const DrawQuad* quad,
+ gfx::QuadF* localQuad, float* edge) const
+{
+ gfx::Rect tileRect = quad->visible_rect;
+
+ bool clipped = false;
+ gfx::QuadF deviceLayerQuad = MathUtil::mapQuad(deviceTransform, gfx::QuadF(quad->visibleContentRect()), clipped);
+ DCHECK(!clipped);
+
+ // TODO(reveman): Axis-aligned is not enough to avoid anti-aliasing.
+ // Bounding rectangle for quad also needs to be expressible as
+ // an integer rectangle. crbug.com/169374
+ bool isAxisAlignedInTarget = deviceLayerQuad.IsRectilinear();
+ bool useAA = !clipped && !isAxisAlignedInTarget && quad->IsEdge();
+
+ if (!useAA)
+ return false;
+
+ LayerQuad deviceLayerBounds = LayerQuad(gfx::QuadF(deviceLayerQuad.BoundingBox()));
+ deviceLayerBounds.inflateAntiAliasingDistance();
+
+ LayerQuad deviceLayerEdges = LayerQuad(deviceLayerQuad);
+ deviceLayerEdges.inflateAntiAliasingDistance();
+
+ deviceLayerEdges.toFloatArray(edge);
+ deviceLayerBounds.toFloatArray(&edge[12]);
+
+ gfx::PointF bottomRight = tileRect.bottom_right();
+ gfx::PointF bottomLeft = tileRect.bottom_left();
+ gfx::PointF topLeft = tileRect.origin();
+ gfx::PointF topRight = tileRect.top_right();
+
+ // Map points to device space.
+ bottomRight = MathUtil::mapPoint(deviceTransform, bottomRight, clipped);
+ DCHECK(!clipped);
+ bottomLeft = MathUtil::mapPoint(deviceTransform, bottomLeft, clipped);
+ DCHECK(!clipped);
+ topLeft = MathUtil::mapPoint(deviceTransform, topLeft, clipped);
+ DCHECK(!clipped);
+ topRight = MathUtil::mapPoint(deviceTransform, topRight, clipped);
+ DCHECK(!clipped);
+
+ LayerQuad::Edge bottomEdge(bottomRight, bottomLeft);
+ LayerQuad::Edge leftEdge(bottomLeft, topLeft);
+ LayerQuad::Edge topEdge(topLeft, topRight);
+ LayerQuad::Edge rightEdge(topRight, bottomRight);
+
+ // Only apply anti-aliasing to edges not clipped by culling or scissoring.
+ if (quad->IsTopEdge() && tileRect.y() == quad->rect.y())
+ topEdge = deviceLayerEdges.top();
+ if (quad->IsLeftEdge() && tileRect.x() == quad->rect.x())
+ leftEdge = deviceLayerEdges.left();
+ if (quad->IsRightEdge() && tileRect.right() == quad->rect.right())
+ rightEdge = deviceLayerEdges.right();
+ if (quad->IsBottomEdge() && tileRect.bottom() == quad->rect.bottom())
+ bottomEdge = deviceLayerEdges.bottom();
+
+ float sign = gfx::QuadF(tileRect).IsCounterClockwise() ? -1 : 1;
+ bottomEdge.scale(sign);
+ leftEdge.scale(sign);
+ topEdge.scale(sign);
+ rightEdge.scale(sign);
+
+ // Create device space quad.
+ LayerQuad deviceQuad(leftEdge, topEdge, rightEdge, bottomEdge);
+
+ // Map device space quad to local space. deviceTransform has no 3d component since it was flattened, so we don't need to project.
+ // We should have already checked that the transform was uninvertible above.
+ gfx::Transform inverseDeviceTransform(gfx::Transform::kSkipInitialization);
+ bool didInvert = deviceTransform.GetInverse(&inverseDeviceTransform);
+ DCHECK(didInvert);
+ *localQuad = MathUtil::mapQuad(inverseDeviceTransform, deviceQuad.ToQuadF(), clipped);
+ // We should not DCHECK(!clipped) here, because anti-aliasing inflation may cause deviceQuad to become
+ // clipped. To our knowledge this scenario does not need to be handled differently than the unclipped case.
+
+ return true;
+}
+
void GLRenderer::drawSolidColorQuad(const DrawingFrame& frame, const SolidColorDrawQuad* quad)
{
- setBlendEnabled(quad->ShouldDrawWithBlending());
+ gfx::Rect tileRect = quad->visible_rect;
- const SolidColorProgram* program = solidColorProgram();
- setUseProgram(program->program());
+ gfx::Transform deviceTransform = frame.windowMatrix * frame.projectionMatrix * quad->quadTransform();
+ deviceTransform.FlattenTo2d();
+ if (!deviceTransform.IsInvertible())
+ return;
+
+ gfx::QuadF localQuad = gfx::QuadF(gfx::RectF(tileRect));
+ float edge[24];
+ bool useAA = setupQuadForAntialiasing(deviceTransform, quad, &localQuad, edge);
+
+ SolidColorProgramUniforms uniforms;
+ if (useAA)
+ solidColorUniformLocation(solidColorProgramAA(), uniforms);
+ else
+ solidColorUniformLocation(solidColorProgram(), uniforms);
+ setUseProgram(uniforms.program);
SkColor color = quad->color;
float opacity = quad->opacity();
float alpha = (SkColorGetA(color) / 255.0) * opacity;
- GLC(context(), context()->uniform4f(program->fragmentShader().colorLocation(), (SkColorGetR(color) / 255.0) * alpha, (SkColorGetG(color) / 255.0) * alpha, (SkColorGetB(color) / 255.0) * alpha, alpha));
+ GLC(context(), context()->uniform4f(uniforms.colorLocation,
+ (SkColorGetR(color) / 255.0) * alpha,
+ (SkColorGetG(color) / 255.0) * alpha,
+ (SkColorGetB(color) / 255.0) * alpha,
+ alpha));
- drawQuadGeometry(frame, quad->quadTransform(), quad->rect, program->vertexShader().matrixLocation());
+ GLC(context(), context()->uniform2f(uniforms.texScaleLocation, 1.0f, 1.0f));
+
+ if (useAA) {
+ GLC(context(), context()->uniform3fv(uniforms.edgeLocation, 8, edge));
+ }
+
+ // Enable blending when the quad properties require it or if we decided
+ // to use antialiasing.
+ setBlendEnabled(quad->ShouldDrawWithBlending() || useAA);
+
+ // Normalize to tileRect.
+ localQuad.Scale(1.0f / tileRect.width(), 1.0f / tileRect.height());
+
+ setShaderQuadF(localQuad, uniforms.pointLocation);
+
+ // The tile quad shader behaves differently compared to all other shaders.
reveman 2013/03/04 22:59:06 we shouldn't be referring to the tile quad shader
ernstm 2013/03/05 00:46:51 Done.
+ // The transform and vertex data are used to figure out the extents that the
+ // un-antialiased quad should have and which vertex this is and the float
+ // quad passed in via uniform is the actual geometry that gets used to draw
+ // it. This is why this centered rect is used and not the original quadRect.
+ gfx::RectF centeredRect(gfx::PointF(-0.5 * tileRect.width(), -0.5 * tileRect.height()), tileRect.size());
+ drawQuadGeometry(frame, quad->quadTransform(), centeredRect, uniforms.matrixLocation);
}
struct TileProgramUniforms {
@@ -813,21 +949,14 @@ void GLRenderer::drawTileQuad(const DrawingFrame& frame, const TileDrawQuad* qua
float fragmentTexScaleX = clampTexRect.width() / textureSize.width();
float fragmentTexScaleY = clampTexRect.height() / textureSize.height();
- gfx::QuadF localQuad;
gfx::Transform deviceTransform = frame.windowMatrix * frame.projectionMatrix * quad->quadTransform();
deviceTransform.FlattenTo2d();
if (!deviceTransform.IsInvertible())
return;
- bool clipped = false;
- gfx::QuadF deviceLayerQuad = MathUtil::mapQuad(deviceTransform, gfx::QuadF(quad->visibleContentRect()), clipped);
- DCHECK(!clipped);
-
- // TODO(reveman): Axis-aligned is not enough to avoid anti-aliasing.
- // Bounding rectangle for quad also needs to be expressible as
- // an integer rectangle. crbug.com/169374
- bool isAxisAlignedInTarget = deviceLayerQuad.IsRectilinear();
- bool useAA = !clipped && !isAxisAlignedInTarget && quad->IsEdge();
+ gfx::QuadF localQuad = gfx::QuadF(gfx::RectF(tileRect));
+ float edge[24];
+ bool useAA = setupQuadForAntialiasing(deviceTransform, quad, &localQuad, edge);
TileProgramUniforms uniforms;
if (useAA) {
@@ -856,68 +985,9 @@ void GLRenderer::drawTileQuad(const DrawingFrame& frame, const TileDrawQuad* qua
ResourceProvider::ScopedSamplerGL quadResourceLock(m_resourceProvider, quad->resource_id, GL_TEXTURE_2D, filter);
if (useAA) {
- LayerQuad deviceLayerBounds = LayerQuad(gfx::QuadF(deviceLayerQuad.BoundingBox()));
- deviceLayerBounds.inflateAntiAliasingDistance();
-
- LayerQuad deviceLayerEdges = LayerQuad(deviceLayerQuad);
- deviceLayerEdges.inflateAntiAliasingDistance();
-
- float edge[24];
- deviceLayerEdges.toFloatArray(edge);
- deviceLayerBounds.toFloatArray(&edge[12]);
GLC(context(), context()->uniform3fv(uniforms.edgeLocation, 8, edge));
-
GLC(context(), context()->uniform4f(uniforms.vertexTexTransformLocation, vertexTexTranslateX, vertexTexTranslateY, vertexTexScaleX, vertexTexScaleY));
GLC(context(), context()->uniform4f(uniforms.fragmentTexTransformLocation, fragmentTexTranslateX, fragmentTexTranslateY, fragmentTexScaleX, fragmentTexScaleY));
-
- gfx::PointF bottomRight = tileRect.bottom_right();
- gfx::PointF bottomLeft = tileRect.bottom_left();
- gfx::PointF topLeft = tileRect.origin();
- gfx::PointF topRight = tileRect.top_right();
-
- // Map points to device space.
- bottomRight = MathUtil::mapPoint(deviceTransform, bottomRight, clipped);
- DCHECK(!clipped);
- bottomLeft = MathUtil::mapPoint(deviceTransform, bottomLeft, clipped);
- DCHECK(!clipped);
- topLeft = MathUtil::mapPoint(deviceTransform, topLeft, clipped);
- DCHECK(!clipped);
- topRight = MathUtil::mapPoint(deviceTransform, topRight, clipped);
- DCHECK(!clipped);
-
- LayerQuad::Edge bottomEdge(bottomRight, bottomLeft);
- LayerQuad::Edge leftEdge(bottomLeft, topLeft);
- LayerQuad::Edge topEdge(topLeft, topRight);
- LayerQuad::Edge rightEdge(topRight, bottomRight);
-
- // Only apply anti-aliasing to edges not clipped by culling or scissoring.
- if (quad->IsTopEdge() && tileRect.y() == quad->rect.y())
- topEdge = deviceLayerEdges.top();
- if (quad->IsLeftEdge() && tileRect.x() == quad->rect.x())
- leftEdge = deviceLayerEdges.left();
- if (quad->IsRightEdge() && tileRect.right() == quad->rect.right())
- rightEdge = deviceLayerEdges.right();
- if (quad->IsBottomEdge() && tileRect.bottom() == quad->rect.bottom())
- bottomEdge = deviceLayerEdges.bottom();
-
- float sign = gfx::QuadF(tileRect).IsCounterClockwise() ? -1 : 1;
- bottomEdge.scale(sign);
- leftEdge.scale(sign);
- topEdge.scale(sign);
- rightEdge.scale(sign);
-
- // Create device space quad.
- LayerQuad deviceQuad(leftEdge, topEdge, rightEdge, bottomEdge);
-
- // Map device space quad to local space. deviceTransform has no 3d component since it was flattened, so we don't need to project.
- // We should have already checked that the transform was uninvertible above.
- gfx::Transform inverseDeviceTransform(gfx::Transform::kSkipInitialization);
- bool didInvert = deviceTransform.GetInverse(&inverseDeviceTransform);
- DCHECK(didInvert);
- localQuad = MathUtil::mapQuad(inverseDeviceTransform, deviceQuad.ToQuadF(), clipped);
-
- // We should not DCHECK(!clipped) here, because anti-aliasing inflation may cause deviceQuad to become
- // clipped. To our knowledge this scenario does not need to be handled differently than the unclipped case.
} else {
// Move fragment shader transform to vertex shader. We can do this while
// still producing correct results as fragmentTexTransformLocation
@@ -931,8 +1001,6 @@ void GLRenderer::drawTileQuad(const DrawingFrame& frame, const TileDrawQuad* qua
vertexTexTranslateY += fragmentTexTranslateY;
GLC(context(), context()->uniform4f(uniforms.vertexTexTransformLocation, vertexTexTranslateX, vertexTexTranslateY, vertexTexScaleX, vertexTexScaleY));
-
- localQuad = gfx::RectF(tileRect);
}
// Enable blending when the quad properties require it or if we decided
@@ -1647,6 +1715,17 @@ const GLRenderer::SolidColorProgram* GLRenderer::solidColorProgram()
return m_solidColorProgram.get();
}
+const GLRenderer::SolidColorProgramAA* GLRenderer::solidColorProgramAA()
+{
+ if (!m_solidColorProgramAA)
+ m_solidColorProgramAA = make_scoped_ptr(new SolidColorProgramAA(m_context));
+ if (!m_solidColorProgramAA->initialized()) {
+ TRACE_EVENT0("cc", "GLRenderer::solidColorProgramAA::initialize");
+ m_solidColorProgramAA->initialize(m_context, m_isUsingBindUniform);
+ }
+ return m_solidColorProgramAA.get();
+}
+
const GLRenderer::RenderPassProgram* GLRenderer::renderPassProgram()
{
DCHECK(m_renderPassProgram);
@@ -1853,6 +1932,8 @@ void GLRenderer::cleanupSharedObjects()
if (m_solidColorProgram)
m_solidColorProgram->cleanup(m_context);
+ if (m_solidColorProgramAA)
+ m_solidColorProgramAA->cleanup(m_context);
if (m_offscreenFramebufferId)
GLC(m_context, m_context->deleteFramebuffer(m_offscreenFramebufferId));
« cc/gl_renderer.h ('K') | « cc/gl_renderer.h ('k') | cc/gl_renderer_pixeltest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698