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

Unified Diff: cc/gl_renderer.cc

Issue 11649005: cc: Support anti-aliasing for solid color layers. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebase and add DrawQuad::AntiAliasing struct. Created 7 years, 11 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 54eef96e72702b364769cb97a438d2a338211053..8f1b463623e2503c908e5629c374b7b7df1f7036 100644
--- a/cc/gl_renderer.cc
+++ b/cc/gl_renderer.cc
@@ -678,18 +678,134 @@ 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();
+}
+
void GLRenderer::drawSolidColorQuad(const DrawingFrame& frame, const SolidColorDrawQuad* quad)
{
- const SolidColorProgram* program = solidColorProgram();
- setUseProgram(program->program());
+ gfx::Rect tileRect = quad->visible_rect;
+
+ gfx::QuadF localQuad;
+ gfx::Transform deviceTransform = MathUtil::to2dTransform(frame.windowMatrix * frame.projectionMatrix * quad->quadTransform());
+ if (!deviceTransform.IsInvertible())
+ return;
+
+ bool clipped = false;
+ gfx::QuadF deviceLayerQuad = MathUtil::mapQuad(deviceTransform, gfx::QuadF(quad->visibleContentRect()), clipped);
+ DCHECK(!clipped);
+
+ SolidColorProgramUniforms uniforms;
+ // For now, we simply skip anti-aliasing with the quad is clipped. This only happens
+ // on perspective transformed layers that go partially behind the camera.
+ if (quad->IsAntialiased() && !clipped)
+ 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));
+
+ bool useAA = !clipped && quad->IsAntialiased();
+ 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));
+
+ 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);
jamesr 2013/01/08 22:29:26 Tons of this code is copy-pasted from drawTileQuad
reveman 2013/01/09 14:20:05 Definitely. I'm saving this until the rest of the
+
+ // Only apply anti-aliasing to edges not clipped by culling or scissoring.
+ if (quad->anti_aliasing.top_edge && tileRect.y() == quad->rect.y())
+ topEdge = deviceLayerEdges.top();
+ if (quad->anti_aliasing.left_edge && tileRect.x() == quad->rect.x())
+ leftEdge = deviceLayerEdges.left();
+ if (quad->anti_aliasing.right_edge && tileRect.right() == quad->rect.right())
+ rightEdge = deviceLayerEdges.right();
+ if (quad->anti_aliasing.bottom_edge && 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 generated with to2dTransform() 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 {
+ localQuad = gfx::RectF(tileRect);
+ }
+
+ // 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.
+ // 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 {
@@ -842,13 +958,13 @@ void GLRenderer::drawTileQuad(const DrawingFrame& frame, const TileDrawQuad* qua
LayerQuad::Edge rightEdge(topRight, bottomRight);
// Only apply anti-aliasing to edges not clipped by culling or scissoring.
- if (quad->top_edge_aa && tileRect.y() == quad->rect.y())
+ if (quad->anti_aliasing.top_edge && tileRect.y() == quad->rect.y())
topEdge = deviceLayerEdges.top();
- if (quad->left_edge_aa && tileRect.x() == quad->rect.x())
+ if (quad->anti_aliasing.left_edge && tileRect.x() == quad->rect.x())
leftEdge = deviceLayerEdges.left();
- if (quad->right_edge_aa && tileRect.right() == quad->rect.right())
+ if (quad->anti_aliasing.right_edge && tileRect.right() == quad->rect.right())
rightEdge = deviceLayerEdges.right();
- if (quad->bottom_edge_aa && tileRect.bottom() == quad->rect.bottom())
+ if (quad->anti_aliasing.bottom_edge && tileRect.bottom() == quad->rect.bottom())
bottomEdge = deviceLayerEdges.bottom();
float sign = gfx::QuadF(tileRect).IsCounterClockwise() ? -1 : 1;
@@ -1582,6 +1698,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);
@@ -1788,6 +1915,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));

Powered by Google App Engine
This is Rietveld 408576698