Home | History | Annotate | Download | only in layers
      1 // Copyright 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "base/containers/hash_tables.h"
      6 #include "cc/layers/append_quads_data.h"
      7 #include "cc/layers/nine_patch_layer_impl.h"
      8 #include "cc/quads/texture_draw_quad.h"
      9 #include "cc/resources/ui_resource_bitmap.h"
     10 #include "cc/resources/ui_resource_client.h"
     11 #include "cc/test/fake_impl_proxy.h"
     12 #include "cc/test/fake_ui_resource_layer_tree_host_impl.h"
     13 #include "cc/test/geometry_test_utils.h"
     14 #include "cc/test/layer_test_common.h"
     15 #include "cc/trees/single_thread_proxy.h"
     16 #include "testing/gmock/include/gmock/gmock.h"
     17 #include "testing/gtest/include/gtest/gtest.h"
     18 #include "ui/gfx/rect_conversions.h"
     19 #include "ui/gfx/safe_integer_conversions.h"
     20 #include "ui/gfx/transform.h"
     21 
     22 namespace cc {
     23 namespace {
     24 
     25 gfx::Rect ToRoundedIntRect(const gfx::RectF& rect_f) {
     26   return gfx::Rect(gfx::ToRoundedInt(rect_f.x()),
     27                    gfx::ToRoundedInt(rect_f.y()),
     28                    gfx::ToRoundedInt(rect_f.width()),
     29                    gfx::ToRoundedInt(rect_f.height()));
     30 }
     31 
     32 void NinePatchLayerLayoutTest(const gfx::Size& bitmap_size,
     33                               const gfx::Rect& aperture_rect,
     34                               const gfx::Size& layer_size,
     35                               const gfx::Rect& border,
     36                               bool fill_center,
     37                               size_t expected_quad_size) {
     38   MockOcclusionTracker<LayerImpl> occlusion_tracker;
     39   scoped_ptr<RenderPass> render_pass = RenderPass::Create();
     40   gfx::Rect visible_content_rect(layer_size);
     41   gfx::Rect expected_remaining(border.x(),
     42                                border.y(),
     43                                layer_size.width() - border.width(),
     44                                layer_size.height() - border.height());
     45 
     46   FakeImplProxy proxy;
     47   TestSharedBitmapManager shared_bitmap_manager;
     48   FakeUIResourceLayerTreeHostImpl host_impl(&proxy, &shared_bitmap_manager);
     49   scoped_ptr<NinePatchLayerImpl> layer =
     50       NinePatchLayerImpl::Create(host_impl.active_tree(), 1);
     51   layer->draw_properties().visible_content_rect = visible_content_rect;
     52   layer->SetBounds(layer_size);
     53   layer->SetContentBounds(layer_size);
     54   layer->CreateRenderSurface();
     55   layer->draw_properties().render_target = layer.get();
     56 
     57   UIResourceId uid = 1;
     58   bool is_opaque = false;
     59   UIResourceBitmap bitmap(bitmap_size, is_opaque);
     60 
     61   host_impl.CreateUIResource(uid, bitmap);
     62   layer->SetUIResourceId(uid);
     63   layer->SetImageBounds(bitmap_size);
     64   layer->SetLayout(aperture_rect, border, fill_center);
     65   AppendQuadsData data;
     66   layer->AppendQuads(render_pass.get(), occlusion_tracker, &data);
     67 
     68   // Verify quad rects
     69   const QuadList& quads = render_pass->quad_list;
     70   EXPECT_EQ(expected_quad_size, quads.size());
     71 
     72   Region remaining(visible_content_rect);
     73   size_t i = 0;
     74   for (QuadList::ConstIterator iter = quads.begin(); iter != quads.end();
     75        ++iter) {
     76     gfx::Rect quad_rect = iter->rect;
     77 
     78     EXPECT_TRUE(visible_content_rect.Contains(quad_rect)) << i;
     79     EXPECT_TRUE(remaining.Contains(quad_rect)) << i;
     80     remaining.Subtract(Region(quad_rect));
     81     ++i;
     82   }
     83 
     84   // Check if the left-over quad is the same size as the mapped aperture quad in
     85   // layer space.
     86   if (!fill_center) {
     87     EXPECT_RECT_EQ(expected_remaining, gfx::ToEnclosedRect(remaining.bounds()));
     88   } else {
     89     EXPECT_TRUE(remaining.bounds().IsEmpty());
     90   }
     91 
     92   // Verify UV rects
     93   gfx::Rect bitmap_rect(bitmap_size);
     94   Region tex_remaining(bitmap_rect);
     95   for (QuadList::ConstIterator iter = quads.begin(); iter != quads.end();
     96        ++iter) {
     97     const TextureDrawQuad* tex_quad = TextureDrawQuad::MaterialCast(&*iter);
     98     gfx::RectF tex_rect =
     99         gfx::BoundingRect(tex_quad->uv_top_left, tex_quad->uv_bottom_right);
    100     tex_rect.Scale(bitmap_size.width(), bitmap_size.height());
    101     tex_remaining.Subtract(Region(ToRoundedIntRect(tex_rect)));
    102   }
    103 
    104   if (!fill_center) {
    105     EXPECT_RECT_EQ(aperture_rect, tex_remaining.bounds());
    106     Region aperture_region(aperture_rect);
    107     EXPECT_EQ(aperture_region, tex_remaining);
    108   } else {
    109     EXPECT_TRUE(remaining.bounds().IsEmpty());
    110   }
    111 }
    112 
    113 TEST(NinePatchLayerImplTest, VerifyDrawQuads) {
    114   // Input is a 100x100 bitmap with a 40x50 aperture at x=20, y=30.
    115   // The bounds of the layer are set to 400x400.
    116   gfx::Size bitmap_size(100, 100);
    117   gfx::Size layer_size(400, 500);
    118   gfx::Rect aperture_rect(20, 30, 40, 50);
    119   gfx::Rect border(40, 40, 80, 80);
    120   bool fill_center = false;
    121   size_t expected_quad_size = 8;
    122   NinePatchLayerLayoutTest(bitmap_size,
    123                            aperture_rect,
    124                            layer_size,
    125                            border,
    126                            fill_center,
    127                            expected_quad_size);
    128 
    129   // The bounds of the layer are set to less than the bitmap size.
    130   bitmap_size = gfx::Size(100, 100);
    131   layer_size = gfx::Size(40, 50);
    132   aperture_rect = gfx::Rect(20, 30, 40, 50);
    133   border = gfx::Rect(10, 10, 25, 15);
    134   fill_center = true;
    135   expected_quad_size = 9;
    136   NinePatchLayerLayoutTest(bitmap_size,
    137                            aperture_rect,
    138                            layer_size,
    139                            border,
    140                            fill_center,
    141                            expected_quad_size);
    142 
    143   // Layer and image sizes are equal.
    144   bitmap_size = gfx::Size(100, 100);
    145   layer_size = gfx::Size(100, 100);
    146   aperture_rect = gfx::Rect(20, 30, 40, 50);
    147   border = gfx::Rect(20, 30, 40, 50);
    148   fill_center = true;
    149   expected_quad_size = 9;
    150   NinePatchLayerLayoutTest(bitmap_size,
    151                            aperture_rect,
    152                            layer_size,
    153                            border,
    154                            fill_center,
    155                            expected_quad_size);
    156 }
    157 
    158 TEST(NinePatchLayerImplTest, VerifyDrawQuadsWithEmptyPatches) {
    159   // The top component of the 9-patch is empty, so there should be no quads for
    160   // the top three components.
    161   gfx::Size bitmap_size(100, 100);
    162   gfx::Size layer_size(100, 100);
    163   gfx::Rect aperture_rect(10, 0, 80, 90);
    164   gfx::Rect border(10, 0, 20, 10);
    165   bool fill_center = false;
    166   size_t expected_quad_size = 5;
    167   NinePatchLayerLayoutTest(bitmap_size,
    168                            aperture_rect,
    169                            layer_size,
    170                            border,
    171                            fill_center,
    172                            expected_quad_size);
    173 
    174   // The top and left components of the 9-patch are empty, so there should be no
    175   // quads for the left and top components.
    176   bitmap_size = gfx::Size(100, 100);
    177   layer_size = gfx::Size(100, 100);
    178   aperture_rect = gfx::Rect(0, 0, 90, 90);
    179   border = gfx::Rect(0, 0, 10, 10);
    180   fill_center = false;
    181   expected_quad_size = 3;
    182   NinePatchLayerLayoutTest(bitmap_size,
    183                            aperture_rect,
    184                            layer_size,
    185                            border,
    186                            fill_center,
    187                            expected_quad_size);
    188 
    189   // The aperture is the size of the bitmap and the center doesn't draw.
    190   bitmap_size = gfx::Size(100, 100);
    191   layer_size = gfx::Size(100, 100);
    192   aperture_rect = gfx::Rect(0, 0, 100, 100);
    193   border = gfx::Rect(0, 0, 0, 0);
    194   fill_center = false;
    195   expected_quad_size = 0;
    196   NinePatchLayerLayoutTest(bitmap_size,
    197                            aperture_rect,
    198                            layer_size,
    199                            border,
    200                            fill_center,
    201                            expected_quad_size);
    202 
    203   // The aperture is the size of the bitmap and the center does draw.
    204   bitmap_size = gfx::Size(100, 100);
    205   layer_size = gfx::Size(100, 100);
    206   aperture_rect = gfx::Rect(0, 0, 100, 100);
    207   border = gfx::Rect(0, 0, 0, 0);
    208   fill_center = true;
    209   expected_quad_size = 1;
    210   NinePatchLayerLayoutTest(bitmap_size,
    211                            aperture_rect,
    212                            layer_size,
    213                            border,
    214                            fill_center,
    215                            expected_quad_size);
    216 }
    217 
    218 TEST(NinePatchLayerImplTest, Occlusion) {
    219   gfx::Size layer_size(1000, 1000);
    220   gfx::Size viewport_size(1000, 1000);
    221 
    222   LayerTestCommon::LayerImplTest impl;
    223 
    224   SkBitmap sk_bitmap;
    225   sk_bitmap.allocN32Pixels(10, 10);
    226   sk_bitmap.setImmutable();
    227   UIResourceId uid = 5;
    228   UIResourceBitmap bitmap(sk_bitmap);
    229   impl.host_impl()->CreateUIResource(uid, bitmap);
    230 
    231   NinePatchLayerImpl* nine_patch_layer_impl =
    232       impl.AddChildToRoot<NinePatchLayerImpl>();
    233   nine_patch_layer_impl->SetBounds(layer_size);
    234   nine_patch_layer_impl->SetContentBounds(layer_size);
    235   nine_patch_layer_impl->SetDrawsContent(true);
    236   nine_patch_layer_impl->SetUIResourceId(uid);
    237   nine_patch_layer_impl->SetImageBounds(gfx::Size(10, 10));
    238 
    239   gfx::Rect aperture = gfx::Rect(3, 3, 4, 4);
    240   gfx::Rect border = gfx::Rect(300, 300, 400, 400);
    241   nine_patch_layer_impl->SetLayout(aperture, border, true);
    242 
    243   impl.CalcDrawProps(viewport_size);
    244 
    245   {
    246     SCOPED_TRACE("No occlusion");
    247     gfx::Rect occluded;
    248     impl.AppendQuadsWithOcclusion(nine_patch_layer_impl, occluded);
    249 
    250     LayerTestCommon::VerifyQuadsExactlyCoverRect(impl.quad_list(),
    251                                                  gfx::Rect(layer_size));
    252     EXPECT_EQ(9u, impl.quad_list().size());
    253   }
    254 
    255   {
    256     SCOPED_TRACE("Full occlusion");
    257     gfx::Rect occluded(nine_patch_layer_impl->visible_content_rect());
    258     impl.AppendQuadsWithOcclusion(nine_patch_layer_impl, occluded);
    259 
    260     LayerTestCommon::VerifyQuadsExactlyCoverRect(impl.quad_list(), gfx::Rect());
    261     EXPECT_EQ(impl.quad_list().size(), 0u);
    262   }
    263 
    264   {
    265     SCOPED_TRACE("Partial occlusion");
    266     gfx::Rect occluded(0, 0, 500, 1000);
    267     impl.AppendQuadsWithOcclusion(nine_patch_layer_impl, occluded);
    268 
    269     size_t partially_occluded_count = 0;
    270     LayerTestCommon::VerifyQuadsAreOccluded(
    271         impl.quad_list(), occluded, &partially_occluded_count);
    272     // The layer outputs nine quads, three of which are partially occluded, and
    273     // three fully occluded.
    274     EXPECT_EQ(6u, impl.quad_list().size());
    275     EXPECT_EQ(3u, partially_occluded_count);
    276   }
    277 }
    278 
    279 }  // namespace
    280 }  // namespace cc
    281