Chromium Code Reviews| 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)); |