15d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Copyright 2012 The Chromium Authors. All rights reserved. 2868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// found in the LICENSE file. 4868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 55d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "cc/output/direct_renderer.h" 6868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 75d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include <utility> 8868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include <vector> 9868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 10a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#include "base/containers/hash_tables.h" 11d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "base/containers/scoped_ptr_hash_map.h" 121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/debug/trace_event.h" 13d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "base/metrics/histogram.h" 145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "cc/base/math_util.h" 151e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "cc/output/copy_output_request.h" 161e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "cc/quads/draw_quad.h" 17868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "ui/gfx/geometry/rect_conversions.h" 18868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "ui/gfx/transform.h" 19868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccistatic gfx::Transform OrthoProjectionMatrix(float left, 211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci float right, 224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) float bottom, 234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) float top) { 244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // Use the standard formula to map the clipping frustum to the cube from 254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // [-1, -1, -1] to [1, 1, 1]. 264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) float delta_x = right - left; 274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) float delta_y = top - bottom; 284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) gfx::Transform proj; 294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (!delta_x || !delta_y) 304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return proj; 314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) proj.matrix().set(0, 0, 2.0f / delta_x); 324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) proj.matrix().set(0, 3, -(right + left) / delta_x); 334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) proj.matrix().set(1, 1, 2.0f / delta_y); 344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) proj.matrix().set(1, 3, -(top + bottom) / delta_y); 354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // Z component of vertices is always set to zero as we don't use the depth 374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // buffer while drawing. 384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) proj.matrix().set(2, 2, 0); 394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return proj; 414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)static gfx::Transform window_matrix(int x, int y, int width, int height) { 444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) gfx::Transform canvas; 454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // Map to window position and scale up to pixel coordinates. 474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) canvas.Translate3d(x, y, 0); 484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) canvas.Scale3d(width, height, 0); 494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // Map from ([-1, -1] to [1, 1]) -> ([0, 0] to [1, 1]) 514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) canvas.Translate3d(0.5, 0.5, 0.5); 524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) canvas.Scale3d(0.5, 0.5, 0.5); 534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return canvas; 554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)namespace cc { 584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)DirectRenderer::DrawingFrame::DrawingFrame() 604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) : root_render_pass(NULL), current_render_pass(NULL), current_texture(NULL) { 614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)DirectRenderer::DrawingFrame::~DrawingFrame() {} 644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// 664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// static 674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)gfx::RectF DirectRenderer::QuadVertexRect() { 684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return gfx::RectF(-0.5f, -0.5f, 1.f, 1.f); 694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 704e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// static 724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void DirectRenderer::QuadRectTransform(gfx::Transform* quad_rect_transform, 734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const gfx::Transform& quad_transform, 744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const gfx::RectF& quad_rect) { 754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) *quad_rect_transform = quad_transform; 764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) quad_rect_transform->Translate(0.5 * quad_rect.width() + quad_rect.x(), 774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 0.5 * quad_rect.height() + quad_rect.y()); 784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) quad_rect_transform->Scale(quad_rect.width(), quad_rect.height()); 794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void DirectRenderer::InitializeViewport(DrawingFrame* frame, 824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const gfx::Rect& draw_rect, 834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const gfx::Rect& viewport_rect, 844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const gfx::Size& surface_size) { 854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) bool flip_y = FlippedFramebuffer(); 864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) DCHECK_GE(viewport_rect.x(), 0); 884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) DCHECK_GE(viewport_rect.y(), 0); 894e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) DCHECK_LE(viewport_rect.right(), surface_size.width()); 904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) DCHECK_LE(viewport_rect.bottom(), surface_size.height()); 914e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (flip_y) { 924e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) frame->projection_matrix = OrthoProjectionMatrix(draw_rect.x(), 934e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) draw_rect.right(), 944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) draw_rect.bottom(), 954e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) draw_rect.y()); 964e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } else { 974e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) frame->projection_matrix = OrthoProjectionMatrix(draw_rect.x(), 984e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) draw_rect.right(), 994e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) draw_rect.y(), 1004e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) draw_rect.bottom()); 1014e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 1024e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1034e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) gfx::Rect window_rect = viewport_rect; 1044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (flip_y) 1054e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) window_rect.set_y(surface_size.height() - viewport_rect.bottom()); 1064e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) frame->window_matrix = window_matrix(window_rect.x(), 1074e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) window_rect.y(), 1084e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) window_rect.width(), 1094e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) window_rect.height()); 1104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) SetDrawViewport(window_rect); 1114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) current_draw_rect_ = draw_rect; 1134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) current_viewport_rect_ = viewport_rect; 1144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) current_surface_size_ = surface_size; 1154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 1164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)gfx::Rect DirectRenderer::MoveFromDrawToWindowSpace( 1184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const gfx::Rect& draw_rect) const { 1194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) gfx::Rect window_rect = draw_rect; 1204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) window_rect -= current_draw_rect_.OffsetFromOrigin(); 1214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) window_rect += current_viewport_rect_.OffsetFromOrigin(); 1224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (FlippedFramebuffer()) 1234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) window_rect.set_y(current_surface_size_.height() - window_rect.bottom()); 1244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return window_rect; 1254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 1264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)DirectRenderer::DirectRenderer(RendererClient* client, 1284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const LayerTreeSettings* settings, 1294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) OutputSurface* output_surface, 1304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) ResourceProvider* resource_provider) 1314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) : Renderer(client, settings), 1324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) output_surface_(output_surface), 1334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) resource_provider_(resource_provider), 1344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) overlay_processor_( 1354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) new OverlayProcessor(output_surface, resource_provider)) { 1364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) overlay_processor_->Initialize(); 1374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 1384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)DirectRenderer::~DirectRenderer() {} 1404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void DirectRenderer::SetEnlargePassTextureAmountForTesting( 1424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const gfx::Vector2d& amount) { 1434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) enlarge_pass_texture_amount_ = amount; 1444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 1454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void DirectRenderer::DecideRenderPassAllocationsForFrame( 1474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const RenderPassList& render_passes_in_draw_order) { 1484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (!resource_provider_) 1494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return; 1504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) base::hash_map<RenderPassId, gfx::Size> render_passes_in_frame; 1524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) for (size_t i = 0; i < render_passes_in_draw_order.size(); ++i) 153868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) render_passes_in_frame.insert(std::pair<RenderPassId, gfx::Size>( 1544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) render_passes_in_draw_order[i]->id, 1554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) RenderPassTextureSize(render_passes_in_draw_order[i]))); 156868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 157868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) std::vector<RenderPassId> passes_to_delete; 1584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) base::ScopedPtrHashMap<RenderPassId, ScopedResource>::const_iterator 159868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) pass_iter; 160868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) for (pass_iter = render_pass_textures_.begin(); 1611e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) pass_iter != render_pass_textures_.end(); 1621e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) ++pass_iter) { 1631e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) base::hash_map<RenderPassId, gfx::Size>::const_iterator it = 1641e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) render_passes_in_frame.find(pass_iter->first); 1651e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) if (it == render_passes_in_frame.end()) { 1661e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) passes_to_delete.push_back(pass_iter->first); 1671e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) continue; 1681e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 1691e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 1701e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) gfx::Size required_size = it->second; 1711e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) ScopedResource* texture = pass_iter->second; 1721e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) DCHECK(texture); 1731e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 1741e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) bool size_appropriate = texture->size().width() >= required_size.width() && 1751e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) texture->size().height() >= required_size.height(); 1761e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) if (texture->id() && !size_appropriate) 1771e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) texture->Free(); 1781e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 1791e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 1801e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // Delete RenderPass textures from the previous frame that will not be used 1811e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // again. 1821e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) for (size_t i = 0; i < passes_to_delete.size(); ++i) 1831e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) render_pass_textures_.erase(passes_to_delete[i]); 1841e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 1851e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) for (size_t i = 0; i < render_passes_in_draw_order.size(); ++i) { 1861e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) if (!render_pass_textures_.contains(render_passes_in_draw_order[i]->id)) { 187868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) scoped_ptr<ScopedResource> texture = 1881e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) ScopedResource::Create(resource_provider_); 1891e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) render_pass_textures_.set(render_passes_in_draw_order[i]->id, 1901e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) texture.Pass()); 191868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 1920529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 1930529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 1940529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 1950529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochvoid DirectRenderer::DrawFrame(RenderPassList* render_passes_in_draw_order, 1960529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch float device_scale_factor, 1971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const gfx::Rect& device_viewport_rect, 1981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const gfx::Rect& device_clip_rect, 1990529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch bool disable_picture_quad_image_filtering) { 2001e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) TRACE_EVENT0("cc", "DirectRenderer::DrawFrame"); 2011e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) UMA_HISTOGRAM_COUNTS("Renderer4.renderPassCount", 2021e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) render_passes_in_draw_order->size()); 203f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 2045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const RenderPass* root_render_pass = render_passes_in_draw_order->back(); 2055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(root_render_pass); 2065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DrawingFrame frame; 2088bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) frame.render_passes_in_draw_order = render_passes_in_draw_order; 209868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) frame.root_render_pass = root_render_pass; 210868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) frame.root_damage_rect = Capabilities().using_partial_swap 2115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ? root_render_pass->damage_rect 2125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) : root_render_pass->output_rect; 2135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) frame.root_damage_rect.Intersect(gfx::Rect(device_viewport_rect.size())); 2145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) frame.device_viewport_rect = device_viewport_rect; 2155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) frame.device_clip_rect = device_clip_rect; 2165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) frame.disable_picture_quad_image_filtering = 217868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) disable_picture_quad_image_filtering; 2185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 219868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) overlay_processor_->ProcessForOverlays(render_passes_in_draw_order, 2201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci &frame.overlay_list); 2211e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 2221e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) EnsureBackbuffer(); 2231e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 2241e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // Only reshape when we know we are going to draw. Otherwise, the reshape 2251e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // can leave the window at the wrong size if we never draw and the proper 2261e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // viewport size is never set. 227868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) output_surface_->Reshape(device_viewport_rect.size(), device_scale_factor); 228868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 2291e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) BeginDrawingFrame(&frame); 230868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) for (size_t i = 0; i < render_passes_in_draw_order->size(); ++i) { 231868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) RenderPass* pass = render_passes_in_draw_order->at(i); 232868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DrawRenderPass(&frame, pass); 233868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 234868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) for (ScopedPtrVector<CopyOutputRequest>::iterator it = 235868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) pass->copy_requests.begin(); 2361e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) it != pass->copy_requests.end(); 2371e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) ++it) { 2381e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) if (i > 0) { 2391e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // Doing a readback is destructive of our state on Mac, so make sure 2401e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // we restore the state between readbacks. http://crbug.com/99393. 2411e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) UseRenderPass(&frame, pass); 2421e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 2431e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) CopyCurrentRenderPassToBitmap(&frame, pass->copy_requests.take(it)); 2441e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 2451e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 2461e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) FinishDrawingFrame(&frame); 2471e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 2481e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) render_passes_in_draw_order->clear(); 2491e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)} 2501e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 2511e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)gfx::Rect DirectRenderer::ComputeScissorRectForRenderPass( 2521e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) const DrawingFrame* frame) { 2531e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) gfx::Rect render_pass_scissor = frame->current_render_pass->output_rect; 2541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (frame->root_damage_rect == frame->root_render_pass->output_rect || 2561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci !frame->current_render_pass->copy_requests.empty()) 2571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return render_pass_scissor; 2581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci gfx::Transform inverse_transform(gfx::Transform::kSkipInitialization); 260868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (frame->current_render_pass->transform_to_root_target.GetInverse( 261868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) &inverse_transform)) { 262868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // Only intersect inverse-projected damage if the transform is invertible. 263 gfx::Rect damage_rect_in_render_pass_space = 264 MathUtil::ProjectEnclosingClippedRect(inverse_transform, 265 frame->root_damage_rect); 266 render_pass_scissor.Intersect(damage_rect_in_render_pass_space); 267 } 268 269 return render_pass_scissor; 270} 271 272bool DirectRenderer::NeedDeviceClip(const DrawingFrame* frame) const { 273 if (frame->current_render_pass != frame->root_render_pass) 274 return false; 275 276 return !frame->device_clip_rect.Contains(frame->device_viewport_rect); 277} 278 279gfx::Rect DirectRenderer::DeviceClipRectInWindowSpace(const DrawingFrame* frame) 280 const { 281 gfx::Rect device_clip_rect = frame->device_clip_rect; 282 if (FlippedFramebuffer()) 283 device_clip_rect.set_y(current_surface_size_.height() - 284 device_clip_rect.bottom()); 285 return device_clip_rect; 286} 287 288void DirectRenderer::SetScissorStateForQuad(const DrawingFrame* frame, 289 const DrawQuad& quad) { 290 if (quad.isClipped()) { 291 SetScissorTestRectInDrawSpace(frame, quad.clipRect()); 292 return; 293 } 294 if (NeedDeviceClip(frame)) { 295 SetScissorTestRect(DeviceClipRectInWindowSpace(frame)); 296 return; 297 } 298 299 EnsureScissorTestDisabled(); 300} 301 302void DirectRenderer::SetScissorStateForQuadWithRenderPassScissor( 303 const DrawingFrame* frame, 304 const DrawQuad& quad, 305 const gfx::Rect& render_pass_scissor, 306 bool* should_skip_quad) { 307 gfx::Rect quad_scissor_rect = render_pass_scissor; 308 309 if (quad.isClipped()) 310 quad_scissor_rect.Intersect(quad.clipRect()); 311 312 if (quad_scissor_rect.IsEmpty()) { 313 *should_skip_quad = true; 314 return; 315 } 316 317 *should_skip_quad = false; 318 SetScissorTestRectInDrawSpace(frame, quad_scissor_rect); 319} 320 321void DirectRenderer::SetScissorTestRectInDrawSpace( 322 const DrawingFrame* frame, 323 const gfx::Rect& draw_space_rect) { 324 gfx::Rect window_space_rect = MoveFromDrawToWindowSpace(draw_space_rect); 325 if (NeedDeviceClip(frame)) 326 window_space_rect.Intersect(DeviceClipRectInWindowSpace(frame)); 327 SetScissorTestRect(window_space_rect); 328} 329 330void DirectRenderer::FinishDrawingQuadList() {} 331 332void DirectRenderer::DrawRenderPass(DrawingFrame* frame, 333 const RenderPass* render_pass) { 334 TRACE_EVENT0("cc", "DirectRenderer::DrawRenderPass"); 335 if (!UseRenderPass(frame, render_pass)) 336 return; 337 338 bool using_scissor_as_optimization = Capabilities().using_partial_swap; 339 gfx::Rect render_pass_scissor; 340 bool draw_rect_covers_full_surface = true; 341 if (frame->current_render_pass == frame->root_render_pass && 342 !frame->device_viewport_rect.Contains( 343 gfx::Rect(output_surface_->SurfaceSize()))) 344 draw_rect_covers_full_surface = false; 345 346 if (using_scissor_as_optimization) { 347 render_pass_scissor = ComputeScissorRectForRenderPass(frame); 348 SetScissorTestRectInDrawSpace(frame, render_pass_scissor); 349 if (!render_pass_scissor.Contains(frame->current_render_pass->output_rect)) 350 draw_rect_covers_full_surface = false; 351 } 352 353 if (frame->current_render_pass != frame->root_render_pass || 354 settings_->should_clear_root_render_pass) { 355 if (NeedDeviceClip(frame)) { 356 SetScissorTestRect(DeviceClipRectInWindowSpace(frame)); 357 draw_rect_covers_full_surface = false; 358 } else if (!using_scissor_as_optimization) { 359 EnsureScissorTestDisabled(); 360 } 361 362 bool has_external_stencil_test = 363 output_surface_->HasExternalStencilTest() && 364 frame->current_render_pass == frame->root_render_pass; 365 366 DiscardPixels(has_external_stencil_test, draw_rect_covers_full_surface); 367 ClearFramebuffer(frame, has_external_stencil_test); 368 } 369 370 const QuadList& quad_list = render_pass->quad_list; 371 for (QuadList::ConstBackToFrontIterator it = quad_list.BackToFrontBegin(); 372 it != quad_list.BackToFrontEnd(); 373 ++it) { 374 const DrawQuad& quad = *it; 375 bool should_skip_quad = false; 376 377 if (using_scissor_as_optimization) { 378 SetScissorStateForQuadWithRenderPassScissor( 379 frame, quad, render_pass_scissor, &should_skip_quad); 380 } else { 381 SetScissorStateForQuad(frame, quad); 382 } 383 384 if (!should_skip_quad) 385 DoDrawQuad(frame, &quad); 386 } 387 FinishDrawingQuadList(); 388} 389 390bool DirectRenderer::UseRenderPass(DrawingFrame* frame, 391 const RenderPass* render_pass) { 392 frame->current_render_pass = render_pass; 393 frame->current_texture = NULL; 394 395 if (render_pass == frame->root_render_pass) { 396 BindFramebufferToOutputSurface(frame); 397 InitializeViewport(frame, 398 render_pass->output_rect, 399 frame->device_viewport_rect, 400 output_surface_->SurfaceSize()); 401 return true; 402 } 403 404 ScopedResource* texture = render_pass_textures_.get(render_pass->id); 405 DCHECK(texture); 406 407 gfx::Size size = RenderPassTextureSize(render_pass); 408 size.Enlarge(enlarge_pass_texture_amount_.x(), 409 enlarge_pass_texture_amount_.y()); 410 if (!texture->id()) 411 texture->Allocate( 412 size, ResourceProvider::TextureHintImmutableFramebuffer, RGBA_8888); 413 DCHECK(texture->id()); 414 415 return BindFramebufferToTexture(frame, texture, render_pass->output_rect); 416} 417 418bool DirectRenderer::HasAllocatedResourcesForTesting(RenderPassId id) const { 419 ScopedResource* texture = render_pass_textures_.get(id); 420 return texture && texture->id(); 421} 422 423// static 424gfx::Size DirectRenderer::RenderPassTextureSize(const RenderPass* render_pass) { 425 return render_pass->output_rect.size(); 426} 427 428} // namespace cc 429