Commit 04d5d437 authored by jamesr@chromium.org's avatar jamesr@chromium.org

Invert DSF to map from delegated frame to layer space

The size of the frame data from a delegated source will not in general match up
exactly with the delegated layer's bounds. Frame sizes and layer bounds are both
expressed as integers, but frame sizes are in physical pixels and layer bounds
are in device-independent pixels. If the device scale is not an integer, there
may not be an exact mapping between the two spaces. For instance, if the layer
size is 105 x 211 and the device scale is 1.5, the delegated content is
responsible for filling 157.5 x 316.5 physical pixels in the final output. This
isn't really possible so what actually happens is the delegated renderer
produces a frame with a physical size of 158 x 317 pixels and sends that up to
the DRLI. To map this frame into physical space, the DRLI should apply the
inverse of the device scale factor to reflect that the frame covers 105.333 x
211.3333 logical pixels.

Before this patch, DRLI would attempt to scale the frame by (105/158, 211/317)
resulting in the frame being scaled down non-uniformly to try to make 158 x 317
pixels fit into a 157.5 x 316.6 space. This scaling looks bad and ends up
mapping pixels partially outside of the layer's logical bounds into the layer's
logical bounds.

BUG=370074

Review URL: https://codereview.chromium.org/311253004

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@275544 0039d316-1c4b-4281-b951-d872f2087c98
parent 97a5a923
...@@ -20,10 +20,11 @@ ...@@ -20,10 +20,11 @@
namespace cc { namespace cc {
DelegatedRendererLayerImpl::DelegatedRendererLayerImpl( DelegatedRendererLayerImpl::DelegatedRendererLayerImpl(LayerTreeImpl* tree_impl,
LayerTreeImpl* tree_impl, int id) int id)
: LayerImpl(tree_impl, id), : LayerImpl(tree_impl, id),
have_render_passes_to_push_(false), have_render_passes_to_push_(false),
inverse_device_scale_factor_(1.0f),
child_id_(0), child_id_(0),
own_child_id_(false) { own_child_id_(false) {
} }
...@@ -141,13 +142,14 @@ void DelegatedRendererLayerImpl::SetFrameData( ...@@ -141,13 +142,14 @@ void DelegatedRendererLayerImpl::SetFrameData(
resources_.swap(resources_in_frame); resources_.swap(resources_in_frame);
resource_provider->DeclareUsedResourcesFromChild(child_id_, resources_); resource_provider->DeclareUsedResourcesFromChild(child_id_, resources_);
inverse_device_scale_factor_ = 1.0f / frame_data->device_scale_factor;
// Display size is already set so we can compute what the damage rect // Display size is already set so we can compute what the damage rect
// will be in layer space. The damage may exceed the visible portion of // will be in layer space. The damage may exceed the visible portion of
// the frame, so intersect the damage to the layer's bounds. // the frame, so intersect the damage to the layer's bounds.
RenderPass* new_root_pass = render_pass_list.back(); RenderPass* new_root_pass = render_pass_list.back();
gfx::Size frame_size = new_root_pass->output_rect.size(); gfx::Size frame_size = new_root_pass->output_rect.size();
gfx::RectF damage_in_layer = MathUtil::MapClippedRect( gfx::RectF damage_in_layer = damage_in_frame;
DelegatedFrameToLayerSpaceTransform(frame_size), damage_in_frame); damage_in_layer.Scale(inverse_device_scale_factor_);
SetUpdateRect(gfx::IntersectRects( SetUpdateRect(gfx::IntersectRects(
gfx::UnionRects(update_rect(), damage_in_layer), gfx::Rect(bounds()))); gfx::UnionRects(update_rect(), damage_in_layer), gfx::Rect(bounds())));
...@@ -196,17 +198,6 @@ void DelegatedRendererLayerImpl::ReleaseResources() { ...@@ -196,17 +198,6 @@ void DelegatedRendererLayerImpl::ReleaseResources() {
ClearChildId(); ClearChildId();
} }
gfx::Transform DelegatedRendererLayerImpl::DelegatedFrameToLayerSpaceTransform(
const gfx::Size& frame_size) const {
gfx::Size display_size = display_size_.IsEmpty() ? bounds() : display_size_;
gfx::Transform delegated_frame_to_layer_space_transform;
delegated_frame_to_layer_space_transform.Scale(
static_cast<double>(display_size.width()) / frame_size.width(),
static_cast<double>(display_size.height()) / frame_size.height());
return delegated_frame_to_layer_space_transform;
}
static inline int IndexToId(int index) { return index + 1; } static inline int IndexToId(int index) { return index + 1; }
static inline int IdToIndex(int id) { return id - 1; } static inline int IdToIndex(int id) { return id - 1; }
...@@ -242,9 +233,9 @@ void DelegatedRendererLayerImpl::AppendContributingRenderPasses( ...@@ -242,9 +233,9 @@ void DelegatedRendererLayerImpl::AppendContributingRenderPasses(
const RenderPass* root_delegated_render_pass = const RenderPass* root_delegated_render_pass =
render_passes_in_draw_order_.back(); render_passes_in_draw_order_.back();
gfx::Size frame_size = root_delegated_render_pass->output_rect.size(); gfx::Size frame_size = root_delegated_render_pass->output_rect.size();
gfx::Transform delegated_frame_to_root_transform = gfx::Transform delegated_frame_to_root_transform = screen_space_transform();
screen_space_transform() * delegated_frame_to_root_transform.Scale(inverse_device_scale_factor_,
DelegatedFrameToLayerSpaceTransform(frame_size); inverse_device_scale_factor_);
for (size_t i = 0; i < render_passes_in_draw_order_.size() - 1; ++i) { for (size_t i = 0; i < render_passes_in_draw_order_.size() - 1; ++i) {
RenderPass::Id output_render_pass_id(-1, -1); RenderPass::Id output_render_pass_id(-1, -1);
...@@ -416,8 +407,9 @@ void DelegatedRendererLayerImpl::AppendRenderPassQuads( ...@@ -416,8 +407,9 @@ void DelegatedRendererLayerImpl::AppendRenderPassQuads(
// Don't allow areas inside the bounds that are empty. // Don't allow areas inside the bounds that are empty.
DCHECK(display_size_.IsEmpty() || DCHECK(display_size_.IsEmpty() ||
gfx::Rect(display_size_).Contains(gfx::Rect(bounds()))); gfx::Rect(display_size_).Contains(gfx::Rect(bounds())));
gfx::Transform delegated_frame_to_target_transform = gfx::Transform delegated_frame_to_target_transform = draw_transform();
draw_transform() * DelegatedFrameToLayerSpaceTransform(frame_size); delegated_frame_to_target_transform.Scale(inverse_device_scale_factor_,
inverse_device_scale_factor_);
output_shared_quad_state->content_to_target_transform.ConcatTransform( output_shared_quad_state->content_to_target_transform.ConcatTransform(
delegated_frame_to_target_transform); delegated_frame_to_target_transform);
......
...@@ -77,9 +77,6 @@ class CC_EXPORT DelegatedRendererLayerImpl : public LayerImpl { ...@@ -77,9 +77,6 @@ class CC_EXPORT DelegatedRendererLayerImpl : public LayerImpl {
RenderPass::Id delegated_render_pass_id, RenderPass::Id delegated_render_pass_id,
RenderPass::Id* output_render_pass_id) const; RenderPass::Id* output_render_pass_id) const;
gfx::Transform DelegatedFrameToLayerSpaceTransform(
const gfx::Size& frame_size) const;
void AppendRenderPassQuads( void AppendRenderPassQuads(
QuadSink* quad_sink, QuadSink* quad_sink,
AppendQuadsData* append_quads_data, AppendQuadsData* append_quads_data,
...@@ -90,6 +87,7 @@ class CC_EXPORT DelegatedRendererLayerImpl : public LayerImpl { ...@@ -90,6 +87,7 @@ class CC_EXPORT DelegatedRendererLayerImpl : public LayerImpl {
virtual const char* LayerTypeAsString() const OVERRIDE; virtual const char* LayerTypeAsString() const OVERRIDE;
bool have_render_passes_to_push_; bool have_render_passes_to_push_;
float inverse_device_scale_factor_;
ScopedPtrVector<RenderPass> render_passes_in_draw_order_; ScopedPtrVector<RenderPass> render_passes_in_draw_order_;
base::hash_map<RenderPass::Id, int> render_passes_index_by_id_; base::hash_map<RenderPass::Id, int> render_passes_index_by_id_;
ResourceProvider::ResourceIdArray resources_; ResourceProvider::ResourceIdArray resources_;
......
...@@ -6,7 +6,8 @@ ...@@ -6,7 +6,8 @@
namespace cc { namespace cc {
DelegatedFrameData::DelegatedFrameData() {} DelegatedFrameData::DelegatedFrameData() : device_scale_factor(1.0f) {
}
DelegatedFrameData::~DelegatedFrameData() {} DelegatedFrameData::~DelegatedFrameData() {}
......
...@@ -18,6 +18,9 @@ class CC_EXPORT DelegatedFrameData { ...@@ -18,6 +18,9 @@ class CC_EXPORT DelegatedFrameData {
DelegatedFrameData(); DelegatedFrameData();
~DelegatedFrameData(); ~DelegatedFrameData();
// The device scale factor used when generating this frame.
float device_scale_factor;
TransferableResourceArray resource_list; TransferableResourceArray resource_list;
ScopedPtrVector<RenderPass> render_pass_list; ScopedPtrVector<RenderPass> render_pass_list;
......
...@@ -93,6 +93,7 @@ void DelegatingRenderer::DrawFrame(RenderPassList* render_passes_in_draw_order, ...@@ -93,6 +93,7 @@ void DelegatingRenderer::DrawFrame(RenderPassList* render_passes_in_draw_order,
delegated_frame_data_ = make_scoped_ptr(new DelegatedFrameData); delegated_frame_data_ = make_scoped_ptr(new DelegatedFrameData);
DelegatedFrameData& out_data = *delegated_frame_data_; DelegatedFrameData& out_data = *delegated_frame_data_;
out_data.device_scale_factor = device_scale_factor;
// Move the render passes and resources into the |out_frame|. // Move the render passes and resources into the |out_frame|.
out_data.render_pass_list.swap(*render_passes_in_draw_order); out_data.render_pass_list.swap(*render_passes_in_draw_order);
......
...@@ -13,8 +13,10 @@ ...@@ -13,8 +13,10 @@
namespace cc { namespace cc {
FakeDelegatedRendererLayerImpl::FakeDelegatedRendererLayerImpl( FakeDelegatedRendererLayerImpl::FakeDelegatedRendererLayerImpl(
LayerTreeImpl* tree_impl, int id) LayerTreeImpl* tree_impl,
: DelegatedRendererLayerImpl(tree_impl, id) {} int id)
: DelegatedRendererLayerImpl(tree_impl, id) {
}
FakeDelegatedRendererLayerImpl::~FakeDelegatedRendererLayerImpl() {} FakeDelegatedRendererLayerImpl::~FakeDelegatedRendererLayerImpl() {}
...@@ -49,8 +51,10 @@ ResourceProvider::ResourceIdSet FakeDelegatedRendererLayerImpl::Resources() ...@@ -49,8 +51,10 @@ ResourceProvider::ResourceIdSet FakeDelegatedRendererLayerImpl::Resources()
void NoopReturnCallback(const ReturnedResourceArray& returned) {} void NoopReturnCallback(const ReturnedResourceArray& returned) {}
void FakeDelegatedRendererLayerImpl::SetFrameDataForRenderPasses( void FakeDelegatedRendererLayerImpl::SetFrameDataForRenderPasses(
float device_scale_factor,
ScopedPtrVector<RenderPass>* pass_list) { ScopedPtrVector<RenderPass>* pass_list) {
scoped_ptr<DelegatedFrameData> delegated_frame(new DelegatedFrameData); scoped_ptr<DelegatedFrameData> delegated_frame(new DelegatedFrameData);
delegated_frame->device_scale_factor = device_scale_factor;
delegated_frame->render_pass_list.swap(*pass_list); delegated_frame->render_pass_list.swap(*pass_list);
ResourceProvider* resource_provider = layer_tree_impl()->resource_provider(); ResourceProvider* resource_provider = layer_tree_impl()->resource_provider();
......
...@@ -26,7 +26,8 @@ class FakeDelegatedRendererLayerImpl : public DelegatedRendererLayerImpl { ...@@ -26,7 +26,8 @@ class FakeDelegatedRendererLayerImpl : public DelegatedRendererLayerImpl {
} }
ResourceProvider::ResourceIdSet Resources() const; ResourceProvider::ResourceIdSet Resources() const;
void SetFrameDataForRenderPasses(ScopedPtrVector<RenderPass>* pass_list); void SetFrameDataForRenderPasses(float device_scale_factor,
ScopedPtrVector<RenderPass>* pass_list);
protected: protected:
FakeDelegatedRendererLayerImpl(LayerTreeImpl* tree_impl, int id); FakeDelegatedRendererLayerImpl(LayerTreeImpl* tree_impl, int id);
......
...@@ -486,9 +486,8 @@ class LayerTreeHostDelegatedTestLayerUsesFrameDamage ...@@ -486,9 +486,8 @@ class LayerTreeHostDelegatedTestLayerUsesFrameDamage
CreateFrameData(gfx::Rect(0, 0, 20, 20), gfx::Rect(0, 0, 0, 0))); CreateFrameData(gfx::Rect(0, 0, 20, 20), gfx::Rect(0, 0, 0, 0)));
break; break;
case 3: case 3:
// Should create a total amount of gfx::Rect(2, 2, 10, 6) damage. // Should create a total amount of gfx::Rect(2, 2, 8, 6) damage:
// The frame size is 20x20 while the layer is 10x10, so this should // (2, 2, 10, 6) clamped to the root output rect.
// produce a gfx::Rect(1, 1, 5, 3) damage rect.
SetFrameData( SetFrameData(
CreateFrameData(gfx::Rect(0, 0, 20, 20), gfx::Rect(2, 2, 5, 5))); CreateFrameData(gfx::Rect(0, 0, 20, 20), gfx::Rect(2, 2, 5, 5)));
SetFrameData( SetFrameData(
...@@ -535,9 +534,7 @@ class LayerTreeHostDelegatedTestLayerUsesFrameDamage ...@@ -535,9 +534,7 @@ class LayerTreeHostDelegatedTestLayerUsesFrameDamage
gfx::Rect(4, 4, 1, 1))); gfx::Rect(4, 4, 1, 1)));
break; break;
case 13: case 13:
// Should create gfx::Rect(1, 1, 2, 2) of damage. The frame size is // Should create gfx::Rect(1, 1, 2, 2) of damage.
// 5x5 and the display size is now set to 10x10, so this should result
// in a gfx::Rect(2, 2, 4, 4) damage rect.
SetFrameData( SetFrameData(
CreateFrameData(gfx::Rect(0, 0, 5, 5), gfx::Rect(1, 1, 2, 2))); CreateFrameData(gfx::Rect(0, 0, 5, 5), gfx::Rect(1, 1, 2, 2)));
break; break;
...@@ -583,6 +580,7 @@ class LayerTreeHostDelegatedTestLayerUsesFrameDamage ...@@ -583,6 +580,7 @@ class LayerTreeHostDelegatedTestLayerUsesFrameDamage
// ways. // ways.
SetFrameData( SetFrameData(
CreateFrameData(gfx::Rect(0, 0, 10, 10), gfx::Rect(3, 3, 1, 1))); CreateFrameData(gfx::Rect(0, 0, 10, 10), gfx::Rect(3, 3, 1, 1)));
break;
} }
first_draw_for_source_frame_ = true; first_draw_for_source_frame_ = true;
} }
...@@ -616,7 +614,7 @@ class LayerTreeHostDelegatedTestLayerUsesFrameDamage ...@@ -616,7 +614,7 @@ class LayerTreeHostDelegatedTestLayerUsesFrameDamage
EXPECT_EQ(gfx::Rect(10, 10).ToString(), damage_rect.ToString()); EXPECT_EQ(gfx::Rect(10, 10).ToString(), damage_rect.ToString());
break; break;
case 3: case 3:
EXPECT_EQ(gfx::Rect(1, 1, 5, 3).ToString(), damage_rect.ToString()); EXPECT_EQ(gfx::Rect(2, 2, 8, 6).ToString(), damage_rect.ToString());
break; break;
case 4: case 4:
EXPECT_EQ(gfx::Rect().ToString(), damage_rect.ToString()); EXPECT_EQ(gfx::Rect().ToString(), damage_rect.ToString());
...@@ -646,7 +644,7 @@ class LayerTreeHostDelegatedTestLayerUsesFrameDamage ...@@ -646,7 +644,7 @@ class LayerTreeHostDelegatedTestLayerUsesFrameDamage
EXPECT_EQ(gfx::Rect().ToString(), damage_rect.ToString()); EXPECT_EQ(gfx::Rect().ToString(), damage_rect.ToString());
break; break;
case 13: case 13:
EXPECT_EQ(gfx::Rect(2, 2, 4, 4).ToString(), damage_rect.ToString()); EXPECT_EQ(gfx::Rect(1, 1, 2, 2).ToString(), damage_rect.ToString());
break; break;
case 14: case 14:
EXPECT_EQ(gfx::Rect().ToString(), damage_rect.ToString()); EXPECT_EQ(gfx::Rect().ToString(), damage_rect.ToString());
......
...@@ -711,13 +711,15 @@ void ParamTraits<cc::DelegatedFrameData>::Write(Message* m, ...@@ -711,13 +711,15 @@ void ParamTraits<cc::DelegatedFrameData>::Write(Message* m,
const param_type& p) { const param_type& p) {
DCHECK_NE(0u, p.render_pass_list.size()); DCHECK_NE(0u, p.render_pass_list.size());
size_t to_reserve = p.resource_list.size() * sizeof(cc::TransferableResource); size_t to_reserve = sizeof(p.device_scale_factor);
to_reserve += p.resource_list.size() * sizeof(cc::TransferableResource);
for (size_t i = 0; i < p.render_pass_list.size(); ++i) { for (size_t i = 0; i < p.render_pass_list.size(); ++i) {
const cc::RenderPass* pass = p.render_pass_list[i]; const cc::RenderPass* pass = p.render_pass_list[i];
to_reserve += ReserveSizeForRenderPassWrite(*pass); to_reserve += ReserveSizeForRenderPassWrite(*pass);
} }
m->Reserve(to_reserve); m->Reserve(to_reserve);
WriteParam(m, p.device_scale_factor);
WriteParam(m, p.resource_list); WriteParam(m, p.resource_list);
WriteParam(m, p.render_pass_list.size()); WriteParam(m, p.render_pass_list.size());
for (size_t i = 0; i < p.render_pass_list.size(); ++i) for (size_t i = 0; i < p.render_pass_list.size(); ++i)
...@@ -727,6 +729,9 @@ void ParamTraits<cc::DelegatedFrameData>::Write(Message* m, ...@@ -727,6 +729,9 @@ void ParamTraits<cc::DelegatedFrameData>::Write(Message* m,
bool ParamTraits<cc::DelegatedFrameData>::Read(const Message* m, bool ParamTraits<cc::DelegatedFrameData>::Read(const Message* m,
PickleIterator* iter, PickleIterator* iter,
param_type* p) { param_type* p) {
if (!ReadParam(m, iter, &p->device_scale_factor))
return false;
const static size_t kMaxRenderPasses = 10000; const static size_t kMaxRenderPasses = 10000;
size_t num_render_passes; size_t num_render_passes;
...@@ -746,6 +751,7 @@ bool ParamTraits<cc::DelegatedFrameData>::Read(const Message* m, ...@@ -746,6 +751,7 @@ bool ParamTraits<cc::DelegatedFrameData>::Read(const Message* m,
void ParamTraits<cc::DelegatedFrameData>::Log(const param_type& p, void ParamTraits<cc::DelegatedFrameData>::Log(const param_type& p,
std::string* l) { std::string* l) {
l->append("DelegatedFrameData("); l->append("DelegatedFrameData(");
LogParam(p.device_scale_factor, l);
LogParam(p.resource_list, l); LogParam(p.resource_list, l);
l->append(", ["); l->append(", [");
for (size_t i = 0; i < p.render_pass_list.size(); ++i) { for (size_t i = 0; i < p.render_pass_list.size(); ++i) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment