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)); |