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

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: per edge anti-aliasing Created 8 years 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 e9f8254a16b5629a6033aeb278a040d58821218d..424a571ed3dee354603f001320271586c0a30687 100644
--- a/cc/gl_renderer.cc
+++ b/cc/gl_renderer.cc
@@ -685,18 +685,131 @@ 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);
+
+ // Only apply anti-aliasing to edges not clipped by culling or scissoring.
+ if (quad->top_edge_aa && tileRect.y() == quad->rect.y())
+ topEdge = deviceLayerEdges.top();
+ if (quad->left_edge_aa && tileRect.x() == quad->rect.x())
+ leftEdge = deviceLayerEdges.left();
+ if (quad->right_edge_aa && tileRect.right() == quad->rect.right())
+ rightEdge = deviceLayerEdges.right();
+ if (quad->bottom_edge_aa && 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.
+ gfx::Transform deviceTransformInverse = MathUtil::inverse(deviceTransform);
+ localQuad = MathUtil::mapQuad(deviceTransformInverse, 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 {
@@ -1585,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);
@@ -1791,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));
« no previous file with comments | « cc/gl_renderer.h ('k') | cc/gl_renderer_pixeltest.cc » ('j') | cc/solid_color_draw_quad.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698