Index: cc/output/direct_renderer.cc |
diff --git a/cc/output/direct_renderer.cc b/cc/output/direct_renderer.cc |
index 0ae4179deaef141473f276f50eb503cba852f5cb..16034ea85e901d0adf55726d8994b4ddb9bcb166 100644 |
--- a/cc/output/direct_renderer.cc |
+++ b/cc/output/direct_renderer.cc |
@@ -278,27 +278,32 @@ bool DirectRenderer::NeedDeviceClip(const DrawingFrame* frame) const { |
return !frame->device_clip_rect.Contains(frame->device_viewport_rect); |
} |
-gfx::Rect DirectRenderer::DeviceClipRectInWindowSpace(const DrawingFrame* frame) |
- const { |
+gfx::Rect DirectRenderer::DeviceClipRectInDrawSpace( |
+ const DrawingFrame* frame) const { |
gfx::Rect device_clip_rect = frame->device_clip_rect; |
- if (FlippedFramebuffer(frame)) |
- device_clip_rect.set_y(current_surface_size_.height() - |
- device_clip_rect.bottom()); |
+ device_clip_rect -= current_viewport_rect_.OffsetFromOrigin(); |
+ device_clip_rect += current_draw_rect_.OffsetFromOrigin(); |
return device_clip_rect; |
} |
-void DirectRenderer::SetScissorStateForQuad(const DrawingFrame* frame, |
- const DrawQuad& quad) { |
- if (quad.isClipped()) { |
- SetScissorTestRectInDrawSpace(frame, quad.clipRect()); |
- return; |
- } |
- if (NeedDeviceClip(frame)) { |
- SetScissorTestRect(DeviceClipRectInWindowSpace(frame)); |
- return; |
- } |
+gfx::Rect DirectRenderer::DeviceViewportRectInDrawSpace( |
+ const DrawingFrame* frame) const { |
+ gfx::Rect device_viewport_rect = frame->device_viewport_rect; |
+ device_viewport_rect -= current_viewport_rect_.OffsetFromOrigin(); |
+ device_viewport_rect += current_draw_rect_.OffsetFromOrigin(); |
+ return device_viewport_rect; |
+} |
- EnsureScissorTestDisabled(); |
+gfx::Rect DirectRenderer::OutputSurfaceRectInDrawSpace( |
+ const DrawingFrame* frame) const { |
+ if (frame->current_render_pass == frame->root_render_pass) { |
+ gfx::Rect output_surface_rect(output_surface_->SurfaceSize()); |
+ output_surface_rect -= current_viewport_rect_.OffsetFromOrigin(); |
+ output_surface_rect += current_draw_rect_.OffsetFromOrigin(); |
+ return output_surface_rect; |
+ } else { |
+ return frame->current_render_pass->output_rect; |
+ } |
} |
bool DirectRenderer::ShouldSkipQuad(const DrawQuad& quad, |
@@ -315,14 +320,23 @@ bool DirectRenderer::ShouldSkipQuad(const DrawQuad& quad, |
return false; |
} |
-void DirectRenderer::SetScissorStateForQuadWithRenderPassScissor( |
+void DirectRenderer::SetScissorStateForQuad( |
const DrawingFrame* frame, |
const DrawQuad& quad, |
- const gfx::Rect& render_pass_scissor) { |
- gfx::Rect quad_scissor_rect = render_pass_scissor; |
- if (quad.isClipped()) |
- quad_scissor_rect.Intersect(quad.clipRect()); |
- SetScissorTestRectInDrawSpace(frame, quad_scissor_rect); |
+ const gfx::Rect& render_pass_scissor, |
+ bool use_render_pass_scissor) { |
+ if (use_render_pass_scissor) { |
+ gfx::Rect quad_scissor_rect = render_pass_scissor; |
+ if (quad.isClipped()) |
+ quad_scissor_rect.Intersect(quad.clipRect()); |
+ SetScissorTestRectInDrawSpace(frame, quad_scissor_rect); |
+ return; |
+ } else if (quad.isClipped()) { |
+ SetScissorTestRectInDrawSpace(frame, quad.clipRect()); |
+ return; |
+ } |
+ |
+ EnsureScissorTestDisabled(); |
} |
void DirectRenderer::SetScissorTestRectInDrawSpace( |
@@ -330,8 +344,6 @@ void DirectRenderer::SetScissorTestRectInDrawSpace( |
const gfx::Rect& draw_space_rect) { |
gfx::Rect window_space_rect = |
MoveFromDrawToWindowSpace(frame, draw_space_rect); |
- if (NeedDeviceClip(frame)) |
- window_space_rect.Intersect(DeviceClipRectInWindowSpace(frame)); |
SetScissorTestRect(window_space_rect); |
} |
@@ -340,13 +352,9 @@ void DirectRenderer::FinishDrawingQuadList() {} |
void DirectRenderer::DoDrawPolygon(const DrawPolygon& poly, |
DrawingFrame* frame, |
const gfx::Rect& render_pass_scissor, |
- bool using_scissor_as_optimization) { |
- if (using_scissor_as_optimization) { |
- SetScissorStateForQuadWithRenderPassScissor(frame, *poly.original_ref(), |
- render_pass_scissor); |
- } else { |
- SetScissorStateForQuad(frame, *poly.original_ref()); |
- } |
+ bool use_render_pass_scissor) { |
+ SetScissorStateForQuad(frame, *poly.original_ref(), render_pass_scissor, |
+ use_render_pass_scissor); |
// If the poly has not been split, then it is just a normal DrawQuad, |
// and we should save any extra processing that would have to be done. |
@@ -365,14 +373,14 @@ void DirectRenderer::DoDrawPolygon(const DrawPolygon& poly, |
void DirectRenderer::FlushPolygons(ScopedPtrDeque<DrawPolygon>* poly_list, |
DrawingFrame* frame, |
const gfx::Rect& render_pass_scissor, |
- bool using_scissor_as_optimization) { |
+ bool use_render_pass_scissor) { |
if (poly_list->empty()) { |
return; |
} |
BspTree bsp_tree(poly_list); |
BspWalkActionDrawPolygon action_handler(this, frame, render_pass_scissor, |
- using_scissor_as_optimization); |
+ use_render_pass_scissor); |
bsp_tree.TraverseWithActionHandler(&action_handler); |
DCHECK(poly_list->empty()); |
} |
@@ -383,38 +391,53 @@ void DirectRenderer::DrawRenderPass(DrawingFrame* frame, |
if (!UseRenderPass(frame, render_pass)) |
return; |
- bool using_scissor_as_optimization = Capabilities().using_partial_swap; |
- gfx::Rect render_pass_scissor; |
- bool draw_rect_covers_full_surface = true; |
- if (frame->current_render_pass == frame->root_render_pass && |
- !frame->device_viewport_rect.Contains( |
- gfx::Rect(output_surface_->SurfaceSize()))) |
- draw_rect_covers_full_surface = false; |
- |
- if (using_scissor_as_optimization) { |
- render_pass_scissor = ComputeScissorRectForRenderPass(frame); |
- SetScissorTestRectInDrawSpace(frame, render_pass_scissor); |
- if (!render_pass_scissor.Contains(frame->current_render_pass->output_rect)) |
- draw_rect_covers_full_surface = false; |
+ const gfx::Rect surface_rect_in_draw_space = |
+ OutputSurfaceRectInDrawSpace(frame); |
+ gfx::Rect render_pass_scissor_in_draw_space = surface_rect_in_draw_space; |
+ |
+ if (frame->current_render_pass == frame->root_render_pass) { |
+ render_pass_scissor_in_draw_space.Intersect( |
+ DeviceViewportRectInDrawSpace(frame)); |
} |
- if (frame->current_render_pass != frame->root_render_pass || |
- settings_->should_clear_root_render_pass) { |
- if (NeedDeviceClip(frame)) { |
- SetScissorTestRect(DeviceClipRectInWindowSpace(frame)); |
- draw_rect_covers_full_surface = false; |
- } else if (!using_scissor_as_optimization) { |
- EnsureScissorTestDisabled(); |
- } |
+ if (Capabilities().using_partial_swap) { |
+ render_pass_scissor_in_draw_space.Intersect( |
+ ComputeScissorRectForRenderPass(frame)); |
+ } |
- bool has_external_stencil_test = |
- output_surface_->HasExternalStencilTest() && |
- frame->current_render_pass == frame->root_render_pass; |
+ if (NeedDeviceClip(frame)) { |
+ render_pass_scissor_in_draw_space.Intersect( |
+ DeviceClipRectInDrawSpace(frame)); |
+ } |
- DiscardPixels(has_external_stencil_test, draw_rect_covers_full_surface); |
- ClearFramebuffer(frame, has_external_stencil_test); |
+ bool render_pass_is_clipped = |
+ !render_pass_scissor_in_draw_space.Contains(surface_rect_in_draw_space); |
+ bool is_root_render_pass = |
+ frame->current_render_pass == frame->root_render_pass; |
+ bool has_external_stencil_test = |
+ is_root_render_pass && output_surface_->HasExternalStencilTest(); |
+ bool should_clear_surface = |
+ !has_external_stencil_test && |
+ (!is_root_render_pass || settings_->should_clear_root_render_pass); |
+ |
+ // If |has_external_stencil_test| we can't discard or clear. Make sure we |
+ // don't need to. |
+ DCHECK_IMPLIES(has_external_stencil_test, |
+ !frame->current_render_pass->has_transparent_background); |
+ |
+ SurfaceInitializationMode mode; |
+ if (should_clear_surface && render_pass_is_clipped) { |
+ mode = SURFACE_INITIALIZATION_MODE_SCISSORED_CLEAR; |
+ } else if (should_clear_surface) { |
+ mode = SURFACE_INITIALIZATION_MODE_FULL_SURFACE_CLEAR; |
+ } else { |
+ mode = SURFACE_INITIALIZATION_MODE_PRESERVE; |
} |
+ PrepareSurfaceForPass( |
+ frame, mode, |
+ MoveFromDrawToWindowSpace(frame, render_pass_scissor_in_draw_space)); |
+ |
const QuadList& quad_list = render_pass->quad_list; |
ScopedPtrDeque<DrawPolygon> poly_list; |
@@ -425,15 +448,15 @@ void DirectRenderer::DrawRenderPass(DrawingFrame* frame, |
const DrawQuad& quad = **it; |
gfx::QuadF send_quad(quad.visible_rect); |
- if (using_scissor_as_optimization && |
- ShouldSkipQuad(quad, render_pass_scissor)) { |
+ if (render_pass_is_clipped && |
+ ShouldSkipQuad(quad, render_pass_scissor_in_draw_space)) { |
continue; |
} |
if (last_sorting_context_id != quad.shared_quad_state->sorting_context_id) { |
last_sorting_context_id = quad.shared_quad_state->sorting_context_id; |
- FlushPolygons(&poly_list, frame, render_pass_scissor, |
- using_scissor_as_optimization); |
+ FlushPolygons(&poly_list, frame, render_pass_scissor_in_draw_space, |
+ render_pass_is_clipped); |
} |
// This layer is in a 3D sorting context so we add it to the list of |
@@ -448,17 +471,13 @@ void DirectRenderer::DrawRenderPass(DrawingFrame* frame, |
} |
// We are not in a 3d sorting context, so we should draw the quad normally. |
- if (using_scissor_as_optimization) { |
- SetScissorStateForQuadWithRenderPassScissor(frame, quad, |
- render_pass_scissor); |
- } else { |
- SetScissorStateForQuad(frame, quad); |
- } |
+ SetScissorStateForQuad(frame, quad, render_pass_scissor_in_draw_space, |
+ render_pass_is_clipped); |
DoDrawQuad(frame, &quad, nullptr); |
} |
- FlushPolygons(&poly_list, frame, render_pass_scissor, |
- using_scissor_as_optimization); |
+ FlushPolygons(&poly_list, frame, render_pass_scissor_in_draw_space, |
+ render_pass_is_clipped); |
FinishDrawingQuadList(); |
} |
@@ -487,7 +506,14 @@ bool DirectRenderer::UseRenderPass(DrawingFrame* frame, |
size, ResourceProvider::TEXTURE_HINT_IMMUTABLE_FRAMEBUFFER, RGBA_8888); |
DCHECK(texture->id()); |
- return BindFramebufferToTexture(frame, texture, render_pass->output_rect); |
+ if (BindFramebufferToTexture(frame, texture, render_pass->output_rect)) { |
+ InitializeViewport(frame, render_pass->output_rect, |
+ gfx::Rect(render_pass->output_rect.size()), |
+ render_pass->output_rect.size()); |
+ return true; |
+ } |
+ |
+ return false; |
} |
bool DirectRenderer::HasAllocatedResourcesForTesting(RenderPassId id) const { |