Index: cc/gl_renderer.cc |
diff --git a/cc/gl_renderer.cc b/cc/gl_renderer.cc |
index ed179ef0ca855a53b8ed19812385630249dd713d..79ee595451b9b331806bfc1d73aa039e01c16afd 100644 |
--- a/cc/gl_renderer.cc |
+++ b/cc/gl_renderer.cc |
@@ -846,28 +846,168 @@ void GLRenderer::DrawRenderPassQuad(DrawingFrame& frame, |
context_->flush(); |
} |
+struct SolidColorProgramUniforms { |
+ unsigned program; |
+ unsigned matrix_location; |
+ unsigned color_location; |
+ unsigned point_location; |
+ unsigned tex_scale_location; |
+ unsigned edge_location; |
+}; |
+ |
+template<class T> |
+static void SolidColorUniformLocation(T program, |
+ SolidColorProgramUniforms* uniforms) { |
+ uniforms->program = program->program(); |
+ uniforms->matrix_location = program->vertexShader().matrixLocation(); |
+ uniforms->color_location = program->fragmentShader().colorLocation(); |
+ uniforms->point_location = program->vertexShader().pointLocation(); |
+ uniforms->tex_scale_location = program->vertexShader().texScaleLocation(); |
+ uniforms->edge_location = program->fragmentShader().edgeLocation(); |
+} |
+ |
+bool GLRenderer::SetupQuadForAntialiasing( |
+ const gfx::Transform& device_transform, |
+ const DrawQuad* quad, |
+ gfx::QuadF* local_quad, |
+ float edge[24]) const { |
+ gfx::Rect tile_rect = quad->visible_rect; |
+ |
+ bool clipped = false; |
+ gfx::QuadF device_layer_quad = MathUtil::mapQuad( |
+ device_transform, 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 is_axis_aligned_in_target = device_layer_quad.IsRectilinear(); |
+ bool use_aa = !clipped && !is_axis_aligned_in_target && quad->IsEdge(); |
+ |
+ if (!use_aa) |
+ return false; |
+ |
+ LayerQuad device_layer_bounds(gfx::QuadF(device_layer_quad.BoundingBox())); |
+ device_layer_bounds.InflateAntiAliasingDistance(); |
+ |
+ LayerQuad device_layer_edges(device_layer_quad); |
+ device_layer_edges.InflateAntiAliasingDistance(); |
+ |
+ device_layer_edges.ToFloatArray(edge); |
+ device_layer_bounds.ToFloatArray(&edge[12]); |
+ |
+ gfx::PointF bottom_right = tile_rect.bottom_right(); |
+ gfx::PointF bottom_left = tile_rect.bottom_left(); |
+ gfx::PointF top_left = tile_rect.origin(); |
+ gfx::PointF top_right = tile_rect.top_right(); |
+ |
+ // Map points to device space. |
+ bottom_right = MathUtil::mapPoint(device_transform, bottom_right, clipped); |
+ DCHECK(!clipped); |
+ bottom_left = MathUtil::mapPoint(device_transform, bottom_left, clipped); |
+ DCHECK(!clipped); |
+ top_left = MathUtil::mapPoint(device_transform, top_left, clipped); |
+ DCHECK(!clipped); |
+ top_right = MathUtil::mapPoint(device_transform, top_right, clipped); |
+ DCHECK(!clipped); |
+ |
+ LayerQuad::Edge bottom_edge(bottom_right, bottom_left); |
+ LayerQuad::Edge left_edge(bottom_left, top_left); |
+ LayerQuad::Edge top_edge(top_left, top_right); |
+ LayerQuad::Edge right_edge(top_right, bottom_right); |
+ |
+ // Only apply anti-aliasing to edges not clipped by culling or scissoring. |
+ if (quad->IsTopEdge() && tile_rect.y() == quad->rect.y()) |
+ top_edge = device_layer_edges.top(); |
+ if (quad->IsLeftEdge() && tile_rect.x() == quad->rect.x()) |
+ left_edge = device_layer_edges.left(); |
+ if (quad->IsRightEdge() && tile_rect.right() == quad->rect.right()) |
+ right_edge = device_layer_edges.right(); |
+ if (quad->IsBottomEdge() && tile_rect.bottom() == quad->rect.bottom()) |
+ bottom_edge = device_layer_edges.bottom(); |
+ |
+ float sign = gfx::QuadF(tile_rect).IsCounterClockwise() ? -1 : 1; |
+ bottom_edge.scale(sign); |
+ left_edge.scale(sign); |
+ top_edge.scale(sign); |
+ right_edge.scale(sign); |
+ |
+ // Create device space quad. |
+ LayerQuad device_quad(left_edge, top_edge, right_edge, bottom_edge); |
+ |
+ // 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 inverse_device_transform( |
+ gfx::Transform::kSkipInitialization); |
+ bool did_invert = device_transform.GetInverse(&inverse_device_transform); |
+ DCHECK(did_invert); |
+ *local_quad = MathUtil::mapQuad( |
+ inverse_device_transform, device_quad.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 tile_rect = quad->visible_rect; |
- const SolidColorProgram* program = GetSolidColorProgram(); |
- SetUseProgram(program->program()); |
+ gfx::Transform device_transform = |
+ frame.window_matrix * frame.projection_matrix * quad->quadTransform(); |
+ device_transform.FlattenTo2d(); |
+ if (!device_transform.IsInvertible()) |
+ return; |
+ |
+ gfx::QuadF local_quad = gfx::QuadF(gfx::RectF(tile_rect)); |
+ float edge[24]; |
+ bool use_aa = SetupQuadForAntialiasing( |
+ device_transform, quad, &local_quad, edge); |
+ |
+ SolidColorProgramUniforms uniforms; |
+ if (use_aa) |
+ SolidColorUniformLocation(GetSolidColorProgramAA(), &uniforms); |
+ else |
+ SolidColorUniformLocation(GetSolidColorProgram(), &uniforms); |
+ SetUseProgram(uniforms.program); |
SkColor color = quad->color; |
float opacity = quad->opacity(); |
float alpha = (SkColorGetA(color) * (1.0f / 255.0f)) * opacity; |
GLC(Context(), |
- Context()->uniform4f(program->fragmentShader().colorLocation(), |
+ Context()->uniform4f(uniforms.color_location, |
(SkColorGetR(color) * (1.0f / 255.0f)) * alpha, |
(SkColorGetG(color) * (1.0f / 255.0f)) * alpha, |
(SkColorGetB(color) * (1.0f / 255.0f)) * alpha, |
alpha)); |
- DrawQuadGeometry(frame, |
- quad->quadTransform(), |
- quad->rect, |
- program->vertexShader().matrixLocation()); |
+ GLC(Context(), Context()->uniform2f(uniforms.tex_scale_location, 1.0f, 1.0f)); |
+ |
+ if (use_aa) |
+ GLC(Context(), Context()->uniform3fv(uniforms.edge_location, 8, edge)); |
+ |
+ // Enable blending when the quad properties require it or if we decided |
+ // to use antialiasing. |
+ SetBlendEnabled(quad->ShouldDrawWithBlending() || use_aa); |
+ |
+ // Normalize to tileRect. |
+ local_quad.Scale(1.0f / tile_rect.width(), 1.0f / tile_rect.height()); |
+ |
+ SetShaderQuadF(local_quad, uniforms.point_location); |
+ |
+ // 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 centered_rect(gfx::PointF(-0.5f * tile_rect.width(), |
+ -0.5f * tile_rect.height()), |
+ tile_rect.size()); |
+ DrawQuadGeometry(frame, quad->quadTransform(), |
+ centered_rect, uniforms.matrix_location); |
} |
struct TileProgramUniforms { |
@@ -882,18 +1022,18 @@ struct TileProgramUniforms { |
}; |
template <class T> |
-static void TileUniformLocation(T program, TileProgramUniforms& uniforms) { |
- uniforms.program = program->program(); |
- uniforms.vertex_tex_transform_location = |
+static void TileUniformLocation(T program, TileProgramUniforms* uniforms) { |
+ uniforms->program = program->program(); |
+ uniforms->vertex_tex_transform_location = |
program->vertexShader().vertexTexTransformLocation(); |
- uniforms.matrix_location = program->vertexShader().matrixLocation(); |
- uniforms.point_location = program->vertexShader().pointLocation(); |
+ uniforms->matrix_location = program->vertexShader().matrixLocation(); |
+ uniforms->point_location = program->vertexShader().pointLocation(); |
- uniforms.sampler_location = program->fragmentShader().samplerLocation(); |
- uniforms.alpha_location = program->fragmentShader().alphaLocation(); |
- uniforms.fragment_tex_transform_location = |
+ uniforms->sampler_location = program->fragmentShader().samplerLocation(); |
+ uniforms->alpha_location = program->fragmentShader().alphaLocation(); |
+ uniforms->fragment_tex_transform_location = |
program->fragmentShader().fragmentTexTransformLocation(); |
- uniforms.edge_location = program->fragmentShader().edgeLocation(); |
+ uniforms->edge_location = program->fragmentShader().edgeLocation(); |
} |
void GLRenderer::DrawTileQuad(const DrawingFrame& frame, |
@@ -947,41 +1087,34 @@ void GLRenderer::DrawTileQuad(const DrawingFrame& frame, |
float fragment_tex_scale_x = clamp_tex_rect.width() / texture_size.width(); |
float fragment_tex_scale_y = clamp_tex_rect.height() / texture_size.height(); |
- gfx::QuadF local_quad; |
gfx::Transform device_transform = |
frame.window_matrix * frame.projection_matrix * quad->quadTransform(); |
device_transform.FlattenTo2d(); |
if (!device_transform.IsInvertible()) |
return; |
- bool clipped = false; |
- gfx::QuadF device_layer_quad = MathUtil::mapQuad( |
- device_transform, 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 is_axis_aligned_in_target = device_layer_quad.IsRectilinear(); |
- bool use_aa = !clipped && !is_axis_aligned_in_target && quad->IsEdge(); |
+ gfx::QuadF local_quad = gfx::QuadF(gfx::RectF(tile_rect)); |
+ float edge[24]; |
+ bool use_aa = SetupQuadForAntialiasing( |
+ device_transform, quad, &local_quad, edge); |
TileProgramUniforms uniforms; |
if (use_aa) { |
if (quad->swizzle_contents) |
- TileUniformLocation(GetTileProgramSwizzleAA(), uniforms); |
+ TileUniformLocation(GetTileProgramSwizzleAA(), &uniforms); |
else |
- TileUniformLocation(GetTileProgramAA(), uniforms); |
+ TileUniformLocation(GetTileProgramAA(), &uniforms); |
} else { |
if (quad->ShouldDrawWithBlending()) { |
if (quad->swizzle_contents) |
- TileUniformLocation(GetTileProgramSwizzle(), uniforms); |
+ TileUniformLocation(GetTileProgramSwizzle(), &uniforms); |
else |
- TileUniformLocation(GetTileProgram(), uniforms); |
+ TileUniformLocation(GetTileProgram(), &uniforms); |
} else { |
if (quad->swizzle_contents) |
- TileUniformLocation(GetTileProgramSwizzleOpaque(), uniforms); |
+ TileUniformLocation(GetTileProgramSwizzleOpaque(), &uniforms); |
else |
- TileUniformLocation(GetTileProgramOpaque(), uniforms); |
+ TileUniformLocation(GetTileProgramOpaque(), &uniforms); |
} |
} |
@@ -996,15 +1129,6 @@ void GLRenderer::DrawTileQuad(const DrawingFrame& frame, |
resource_provider_, quad->resource_id, GL_TEXTURE_2D, filter); |
if (use_aa) { |
- LayerQuad deviceLayerBounds(gfx::QuadF(device_layer_quad.BoundingBox())); |
- deviceLayerBounds.InflateAntiAliasingDistance(); |
- |
- LayerQuad device_layer_edges(device_layer_quad); |
- device_layer_edges.InflateAntiAliasingDistance(); |
- |
- float edge[24]; |
- device_layer_edges.ToFloatArray(edge); |
- deviceLayerBounds.ToFloatArray(&edge[12]); |
GLC(Context(), Context()->uniform3fv(uniforms.edge_location, 8, edge)); |
GLC(Context(), |
@@ -1019,59 +1143,6 @@ void GLRenderer::DrawTileQuad(const DrawingFrame& frame, |
fragment_tex_translate_y, |
fragment_tex_scale_x, |
fragment_tex_scale_y)); |
- |
- gfx::PointF bottom_right = tile_rect.bottom_right(); |
- gfx::PointF bottom_left = tile_rect.bottom_left(); |
- gfx::PointF top_left = tile_rect.origin(); |
- gfx::PointF top_right = tile_rect.top_right(); |
- |
- // Map points to device space. |
- bottom_right = MathUtil::mapPoint(device_transform, bottom_right, clipped); |
- DCHECK(!clipped); |
- bottom_left = MathUtil::mapPoint(device_transform, bottom_left, clipped); |
- DCHECK(!clipped); |
- top_left = MathUtil::mapPoint(device_transform, top_left, clipped); |
- DCHECK(!clipped); |
- top_right = MathUtil::mapPoint(device_transform, top_right, clipped); |
- DCHECK(!clipped); |
- |
- LayerQuad::Edge bottom_edge(bottom_right, bottom_left); |
- LayerQuad::Edge left_edge(bottom_left, top_left); |
- LayerQuad::Edge top_edge(top_left, top_right); |
- LayerQuad::Edge right_edge(top_right, bottom_right); |
- |
- // Only apply anti-aliasing to edges not clipped by culling or scissoring. |
- if (quad->IsTopEdge() && tile_rect.y() == quad->rect.y()) |
- top_edge = device_layer_edges.top(); |
- if (quad->IsLeftEdge() && tile_rect.x() == quad->rect.x()) |
- left_edge = device_layer_edges.left(); |
- if (quad->IsRightEdge() && tile_rect.right() == quad->rect.right()) |
- right_edge = device_layer_edges.right(); |
- if (quad->IsBottomEdge() && tile_rect.bottom() == quad->rect.bottom()) |
- bottom_edge = device_layer_edges.bottom(); |
- |
- float sign = gfx::QuadF(tile_rect).IsCounterClockwise() ? -1 : 1; |
- bottom_edge.scale(sign); |
- left_edge.scale(sign); |
- top_edge.scale(sign); |
- right_edge.scale(sign); |
- |
- // Create device space quad. |
- LayerQuad device_quad(left_edge, top_edge, right_edge, bottom_edge); |
- |
- // Map device space quad to local space. device_transform 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 inverse_device_transform( |
- gfx::Transform::kSkipInitialization); |
- bool did_invert = device_transform.GetInverse(&inverse_device_transform); |
- DCHECK(did_invert); |
- local_quad = MathUtil::mapQuad( |
- inverse_device_transform, device_quad.ToQuadF(), clipped); |
- |
- // We should not DCHECK(!clipped) here, because anti-aliasing inflation may |
- // cause device_quad 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 fragment_tex_transform_location |
@@ -1090,8 +1161,6 @@ void GLRenderer::DrawTileQuad(const DrawingFrame& frame, |
vertex_tex_translate_y, |
vertex_tex_scale_x, |
vertex_tex_scale_y)); |
- |
- local_quad = gfx::RectF(tile_rect); |
} |
// Enable blending when the quad properties require it or if we decided |
@@ -1104,7 +1173,6 @@ void GLRenderer::DrawTileQuad(const DrawingFrame& frame, |
SetShaderOpacity(quad->opacity(), uniforms.alpha_location); |
SetShaderQuadF(local_quad, uniforms.point_location); |
- // 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 |
@@ -1902,9 +1970,10 @@ bool GLRenderer::InitializeSharedObjects() { |
const GLRenderer::TileCheckerboardProgram* |
GLRenderer::GetTileCheckerboardProgram() { |
- if (!tile_checkerboard_program_) |
+ if (!tile_checkerboard_program_) { |
tile_checkerboard_program_ = |
make_scoped_ptr(new TileCheckerboardProgram(context_)); |
+ } |
if (!tile_checkerboard_program_->initialized()) { |
TRACE_EVENT0("cc", "GLRenderer::checkerboardProgram::initalize"); |
tile_checkerboard_program_->initialize(context_, is_using_bind_uniform_); |
@@ -1922,6 +1991,19 @@ const GLRenderer::SolidColorProgram* GLRenderer::GetSolidColorProgram() { |
return solid_color_program_.get(); |
} |
+const GLRenderer::SolidColorProgramAA* GLRenderer::GetSolidColorProgramAA() |
+{ |
+ if (!solid_color_program_aa_) { |
+ solid_color_program_aa_ = |
+ make_scoped_ptr(new SolidColorProgramAA(context_)); |
+ } |
+ if (!solid_color_program_aa_->initialized()) { |
+ TRACE_EVENT0("cc", "GLRenderer::solidColorProgramAA::initialize"); |
+ solid_color_program_aa_->initialize(context_, is_using_bind_uniform_); |
+ } |
+ return solid_color_program_aa_.get(); |
+} |
+ |
const GLRenderer::RenderPassProgram* GLRenderer::GetRenderPassProgram() { |
DCHECK(render_pass_program_); |
if (!render_pass_program_->initialized()) { |
@@ -2124,6 +2206,8 @@ void GLRenderer::CleanupSharedObjects() { |
if (solid_color_program_) |
solid_color_program_->cleanup(context_); |
+ if (solid_color_program_aa_) |
+ solid_color_program_aa_->cleanup(context_); |
if (offscreen_framebuffer_id_) |
GLC(context_, context_->deleteFramebuffer(offscreen_framebuffer_id_)); |