| OLD | NEW |
| 1 // Copyright 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "cc/layers/texture_layer.h" | 5 #include "cc/layers/texture_layer.h" |
| 6 | 6 |
| 7 #include <algorithm> | |
| 8 #include <string> | 7 #include <string> |
| 9 | 8 |
| 10 #include "base/bind.h" | |
| 11 #include "base/callback.h" | 9 #include "base/callback.h" |
| 12 #include "cc/layers/solid_color_layer.h" | |
| 13 #include "cc/layers/texture_layer_client.h" | 10 #include "cc/layers/texture_layer_client.h" |
| 14 #include "cc/layers/texture_layer_impl.h" | 11 #include "cc/layers/texture_layer_impl.h" |
| 15 #include "cc/output/compositor_frame_ack.h" | |
| 16 #include "cc/output/context_provider.h" | |
| 17 #include "cc/resources/returned_resource.h" | |
| 18 #include "cc/test/fake_impl_proxy.h" | 12 #include "cc/test/fake_impl_proxy.h" |
| 19 #include "cc/test/fake_layer_tree_host_client.h" | 13 #include "cc/test/fake_layer_tree_host_client.h" |
| 20 #include "cc/test/fake_layer_tree_host_impl.h" | 14 #include "cc/test/fake_layer_tree_host_impl.h" |
| 21 #include "cc/test/layer_test_common.h" | 15 #include "cc/test/layer_test_common.h" |
| 22 #include "cc/test/layer_tree_test.h" | 16 #include "cc/test/layer_tree_test.h" |
| 23 #include "cc/trees/layer_tree_host.h" | 17 #include "cc/trees/layer_tree_host.h" |
| 24 #include "cc/trees/layer_tree_impl.h" | 18 #include "cc/trees/layer_tree_impl.h" |
| 25 #include "cc/trees/single_thread_proxy.h" | 19 #include "cc/trees/single_thread_proxy.h" |
| 26 #include "gpu/GLES2/gl2extchromium.h" | 20 #include "gpu/GLES2/gl2extchromium.h" |
| 27 #include "testing/gmock/include/gmock/gmock.h" | 21 #include "testing/gmock/include/gmock/gmock.h" |
| (...skipping 870 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 898 | 892 |
| 899 // Used on either thread, protected by lock_. | 893 // Used on either thread, protected by lock_. |
| 900 base::Lock lock_; | 894 base::Lock lock_; |
| 901 unsigned expected_used_textures_on_commit_; | 895 unsigned expected_used_textures_on_commit_; |
| 902 }; | 896 }; |
| 903 | 897 |
| 904 // The TextureLayerClient does not use mailboxes, so can't use a delegating | 898 // The TextureLayerClient does not use mailboxes, so can't use a delegating |
| 905 // renderer. | 899 // renderer. |
| 906 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(TextureLayerClientTest); | 900 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(TextureLayerClientTest); |
| 907 | 901 |
| 908 | |
| 909 // Checks that changing a texture in the client for a TextureLayer that's | |
| 910 // invisible correctly works without drawing a deleted texture. See | |
| 911 // crbug.com/266628 | |
| 912 class TextureLayerChangeInvisibleTest | |
| 913 : public LayerTreeTest, | |
| 914 public TextureLayerClient { | |
| 915 public: | |
| 916 TextureLayerChangeInvisibleTest() | |
| 917 : client_context_(TestWebGraphicsContext3D::Create()), | |
| 918 texture_(client_context_->createTexture()), | |
| 919 texture_to_delete_on_next_commit_(0), | |
| 920 prepare_called_(0), | |
| 921 commit_count_(0), | |
| 922 expected_texture_on_draw_(0) {} | |
| 923 | |
| 924 // TextureLayerClient implementation. | |
| 925 virtual unsigned PrepareTexture() OVERRIDE { | |
| 926 ++prepare_called_; | |
| 927 return texture_; | |
| 928 } | |
| 929 | |
| 930 // TextureLayerClient implementation. | |
| 931 virtual WebKit::WebGraphicsContext3D* Context3d() OVERRIDE { | |
| 932 return client_context_.get(); | |
| 933 } | |
| 934 | |
| 935 // TextureLayerClient implementation. | |
| 936 virtual bool PrepareTextureMailbox( | |
| 937 cc::TextureMailbox* mailbox, bool use_shared_memory) OVERRIDE { | |
| 938 return false; | |
| 939 } | |
| 940 | |
| 941 virtual void SetupTree() OVERRIDE { | |
| 942 scoped_refptr<Layer> root = Layer::Create(); | |
| 943 root->SetBounds(gfx::Size(10, 10)); | |
| 944 root->SetAnchorPoint(gfx::PointF()); | |
| 945 root->SetIsDrawable(true); | |
| 946 | |
| 947 solid_layer_ = SolidColorLayer::Create(); | |
| 948 solid_layer_->SetBounds(gfx::Size(10, 10)); | |
| 949 solid_layer_->SetIsDrawable(true); | |
| 950 solid_layer_->SetBackgroundColor(SK_ColorWHITE); | |
| 951 root->AddChild(solid_layer_); | |
| 952 | |
| 953 parent_layer_ = Layer::Create(); | |
| 954 parent_layer_->SetBounds(gfx::Size(10, 10)); | |
| 955 parent_layer_->SetIsDrawable(true); | |
| 956 root->AddChild(parent_layer_); | |
| 957 | |
| 958 texture_layer_ = TextureLayer::Create(this); | |
| 959 texture_layer_->SetBounds(gfx::Size(10, 10)); | |
| 960 texture_layer_->SetAnchorPoint(gfx::PointF()); | |
| 961 texture_layer_->SetIsDrawable(true); | |
| 962 parent_layer_->AddChild(texture_layer_); | |
| 963 | |
| 964 layer_tree_host()->SetRootLayer(root); | |
| 965 LayerTreeTest::SetupTree(); | |
| 966 } | |
| 967 | |
| 968 virtual void BeginTest() OVERRIDE { | |
| 969 PostSetNeedsCommitToMainThread(); | |
| 970 } | |
| 971 | |
| 972 virtual void DidCommitAndDrawFrame() OVERRIDE { | |
| 973 ++commit_count_; | |
| 974 switch (commit_count_) { | |
| 975 case 1: | |
| 976 // We should have updated the layer, committing the texture. | |
| 977 EXPECT_EQ(1, prepare_called_); | |
| 978 // Make layer invisible. | |
| 979 parent_layer_->SetOpacity(0.f); | |
| 980 break; | |
| 981 case 2: { | |
| 982 // Layer shouldn't have been updated. | |
| 983 EXPECT_EQ(1, prepare_called_); | |
| 984 // Change the texture. | |
| 985 texture_to_delete_on_next_commit_ = texture_; | |
| 986 texture_ = client_context_->createTexture(); | |
| 987 texture_layer_->SetNeedsDisplay(); | |
| 988 // Force a change to make sure we draw a frame. | |
| 989 solid_layer_->SetBackgroundColor(SK_ColorGRAY); | |
| 990 break; | |
| 991 } | |
| 992 case 3: | |
| 993 EXPECT_EQ(1, prepare_called_); | |
| 994 client_context_->deleteTexture(texture_to_delete_on_next_commit_); | |
| 995 texture_to_delete_on_next_commit_ = 0; | |
| 996 // Make layer visible again. | |
| 997 parent_layer_->SetOpacity(1.f); | |
| 998 break; | |
| 999 case 4: { | |
| 1000 // Layer should have been updated. | |
| 1001 EXPECT_EQ(2, prepare_called_); | |
| 1002 texture_layer_->ClearClient(); | |
| 1003 client_context_->deleteTexture(texture_); | |
| 1004 texture_ = 0; | |
| 1005 break; | |
| 1006 } | |
| 1007 case 5: | |
| 1008 EndTest(); | |
| 1009 break; | |
| 1010 default: | |
| 1011 NOTREACHED(); | |
| 1012 break; | |
| 1013 } | |
| 1014 } | |
| 1015 | |
| 1016 virtual void BeginCommitOnThread(LayerTreeHostImpl* host_impl) OVERRIDE { | |
| 1017 ASSERT_TRUE(proxy()->IsMainThreadBlocked()); | |
| 1018 // This is the only texture that can be drawn this frame. | |
| 1019 expected_texture_on_draw_ = texture_; | |
| 1020 } | |
| 1021 | |
| 1022 virtual bool PrepareToDrawOnThread(LayerTreeHostImpl* host_impl, | |
| 1023 LayerTreeHostImpl::FrameData* frame_data, | |
| 1024 bool result) OVERRIDE { | |
| 1025 ContextForImplThread(host_impl)->ResetUsedTextures(); | |
| 1026 return true; | |
| 1027 } | |
| 1028 | |
| 1029 virtual void SwapBuffersOnThread(LayerTreeHostImpl* host_impl, | |
| 1030 bool result) OVERRIDE { | |
| 1031 ASSERT_TRUE(result); | |
| 1032 TestWebGraphicsContext3D* context = ContextForImplThread(host_impl); | |
| 1033 int used_textures = context->NumUsedTextures(); | |
| 1034 switch (host_impl->active_tree()->source_frame_number()) { | |
| 1035 case 0: | |
| 1036 EXPECT_EQ(1, used_textures); | |
| 1037 EXPECT_TRUE(context->UsedTexture(expected_texture_on_draw_)); | |
| 1038 break; | |
| 1039 case 1: | |
| 1040 case 2: | |
| 1041 EXPECT_EQ(0, used_textures); | |
| 1042 break; | |
| 1043 case 3: | |
| 1044 EXPECT_EQ(1, used_textures); | |
| 1045 EXPECT_TRUE(context->UsedTexture(expected_texture_on_draw_)); | |
| 1046 break; | |
| 1047 default: | |
| 1048 break; | |
| 1049 } | |
| 1050 } | |
| 1051 | |
| 1052 virtual void AfterTest() OVERRIDE {} | |
| 1053 | |
| 1054 private: | |
| 1055 TestWebGraphicsContext3D* ContextForImplThread(LayerTreeHostImpl* host_impl) { | |
| 1056 return static_cast<TestWebGraphicsContext3D*>( | |
| 1057 host_impl->output_surface()->context_provider()->Context3d()); | |
| 1058 } | |
| 1059 | |
| 1060 scoped_refptr<SolidColorLayer> solid_layer_; | |
| 1061 scoped_refptr<Layer> parent_layer_; | |
| 1062 scoped_refptr<TextureLayer> texture_layer_; | |
| 1063 scoped_ptr<TestWebGraphicsContext3D> client_context_; | |
| 1064 | |
| 1065 // Used on the main thread, and on the impl thread while the main thread is | |
| 1066 // blocked. | |
| 1067 unsigned texture_; | |
| 1068 | |
| 1069 // Used on the main thread. | |
| 1070 unsigned texture_to_delete_on_next_commit_; | |
| 1071 int prepare_called_; | |
| 1072 int commit_count_; | |
| 1073 | |
| 1074 // Used on the compositor thread. | |
| 1075 unsigned expected_texture_on_draw_; | |
| 1076 }; | |
| 1077 | |
| 1078 // The TextureLayerChangeInvisibleTest does not use mailboxes, so can't use a | |
| 1079 // delegating renderer. | |
| 1080 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(TextureLayerChangeInvisibleTest); | |
| 1081 | |
| 1082 // Checks that changing a mailbox in the client for a TextureLayer that's | |
| 1083 // invisible correctly works and uses the new mailbox as soon as the layer | |
| 1084 // becomes visible (and returns the old one). | |
| 1085 class TextureLayerChangeInvisibleMailboxTest | |
| 1086 : public LayerTreeTest, | |
| 1087 public TextureLayerClient { | |
| 1088 public: | |
| 1089 TextureLayerChangeInvisibleMailboxTest() | |
| 1090 : mailbox_changed_(true), | |
| 1091 mailbox_returned_(0), | |
| 1092 prepare_called_(0), | |
| 1093 commit_count_(0) { | |
| 1094 mailbox_ = MakeMailbox('1'); | |
| 1095 } | |
| 1096 | |
| 1097 // TextureLayerClient implementation. | |
| 1098 virtual unsigned PrepareTexture() OVERRIDE { | |
| 1099 NOTREACHED(); | |
| 1100 return 0; | |
| 1101 } | |
| 1102 | |
| 1103 // TextureLayerClient implementation. | |
| 1104 virtual WebKit::WebGraphicsContext3D* Context3d() OVERRIDE { | |
| 1105 NOTREACHED(); | |
| 1106 return NULL; | |
| 1107 } | |
| 1108 | |
| 1109 // TextureLayerClient implementation. | |
| 1110 virtual bool PrepareTextureMailbox( | |
| 1111 cc::TextureMailbox* mailbox, bool use_shared_memory) OVERRIDE { | |
| 1112 ++prepare_called_; | |
| 1113 if (!mailbox_changed_) | |
| 1114 return false; | |
| 1115 *mailbox = mailbox_; | |
| 1116 return true; | |
| 1117 } | |
| 1118 | |
| 1119 TextureMailbox MakeMailbox(char name) { | |
| 1120 return TextureMailbox( | |
| 1121 std::string(64, name), | |
| 1122 base::Bind(&TextureLayerChangeInvisibleMailboxTest::MailboxReleased, | |
| 1123 base::Unretained(this))); | |
| 1124 } | |
| 1125 | |
| 1126 void MailboxReleased(unsigned sync_point, bool lost_resource) { | |
| 1127 ++mailbox_returned_; | |
| 1128 } | |
| 1129 | |
| 1130 virtual void SetupTree() OVERRIDE { | |
| 1131 scoped_refptr<Layer> root = Layer::Create(); | |
| 1132 root->SetBounds(gfx::Size(10, 10)); | |
| 1133 root->SetAnchorPoint(gfx::PointF()); | |
| 1134 root->SetIsDrawable(true); | |
| 1135 | |
| 1136 solid_layer_ = SolidColorLayer::Create(); | |
| 1137 solid_layer_->SetBounds(gfx::Size(10, 10)); | |
| 1138 solid_layer_->SetIsDrawable(true); | |
| 1139 solid_layer_->SetBackgroundColor(SK_ColorWHITE); | |
| 1140 root->AddChild(solid_layer_); | |
| 1141 | |
| 1142 parent_layer_ = Layer::Create(); | |
| 1143 parent_layer_->SetBounds(gfx::Size(10, 10)); | |
| 1144 parent_layer_->SetIsDrawable(true); | |
| 1145 root->AddChild(parent_layer_); | |
| 1146 | |
| 1147 texture_layer_ = TextureLayer::CreateForMailbox(this); | |
| 1148 texture_layer_->SetBounds(gfx::Size(10, 10)); | |
| 1149 texture_layer_->SetAnchorPoint(gfx::PointF()); | |
| 1150 texture_layer_->SetIsDrawable(true); | |
| 1151 parent_layer_->AddChild(texture_layer_); | |
| 1152 | |
| 1153 layer_tree_host()->SetRootLayer(root); | |
| 1154 LayerTreeTest::SetupTree(); | |
| 1155 } | |
| 1156 | |
| 1157 virtual void BeginTest() OVERRIDE { | |
| 1158 PostSetNeedsCommitToMainThread(); | |
| 1159 } | |
| 1160 | |
| 1161 virtual void DidCommitAndDrawFrame() OVERRIDE { | |
| 1162 ++commit_count_; | |
| 1163 switch (commit_count_) { | |
| 1164 case 1: | |
| 1165 // We should have updated the layer, committing the texture. | |
| 1166 EXPECT_EQ(1, prepare_called_); | |
| 1167 // Make layer invisible. | |
| 1168 parent_layer_->SetOpacity(0.f); | |
| 1169 break; | |
| 1170 case 2: | |
| 1171 // Layer shouldn't have been updated. | |
| 1172 EXPECT_EQ(1, prepare_called_); | |
| 1173 // Change the texture. | |
| 1174 mailbox_ = MakeMailbox('2'); | |
| 1175 mailbox_changed_ = true; | |
| 1176 texture_layer_->SetNeedsDisplay(); | |
| 1177 // Force a change to make sure we draw a frame. | |
| 1178 solid_layer_->SetBackgroundColor(SK_ColorGRAY); | |
| 1179 break; | |
| 1180 case 3: | |
| 1181 // Layer shouldn't have been updated. | |
| 1182 EXPECT_EQ(1, prepare_called_); | |
| 1183 // So the old mailbox isn't returned yet. | |
| 1184 EXPECT_EQ(0, mailbox_returned_); | |
| 1185 // Make layer visible again. | |
| 1186 parent_layer_->SetOpacity(1.f); | |
| 1187 break; | |
| 1188 case 4: | |
| 1189 // Layer should have been updated. | |
| 1190 EXPECT_EQ(2, prepare_called_); | |
| 1191 // So the old mailbox should have been returned already. | |
| 1192 EXPECT_EQ(1, mailbox_returned_); | |
| 1193 texture_layer_->ClearClient(); | |
| 1194 break; | |
| 1195 case 5: | |
| 1196 EXPECT_EQ(2, mailbox_returned_); | |
| 1197 EndTest(); | |
| 1198 break; | |
| 1199 default: | |
| 1200 NOTREACHED(); | |
| 1201 break; | |
| 1202 } | |
| 1203 } | |
| 1204 | |
| 1205 virtual void SwapBuffersOnThread(LayerTreeHostImpl* host_impl, | |
| 1206 bool result) OVERRIDE { | |
| 1207 ASSERT_TRUE(result); | |
| 1208 DelegatedFrameData* delegated_frame_data = | |
| 1209 output_surface()->last_sent_frame().delegated_frame_data.get(); | |
| 1210 if (!delegated_frame_data) | |
| 1211 return; | |
| 1212 | |
| 1213 // Return all resources immediately. | |
| 1214 TransferableResourceArray resources_to_return = | |
| 1215 output_surface()->resources_held_by_parent(); | |
| 1216 | |
| 1217 CompositorFrameAck ack; | |
| 1218 for (size_t i = 0; i < resources_to_return.size(); ++i) | |
| 1219 output_surface()->ReturnResource(resources_to_return[i].id, &ack); | |
| 1220 host_impl->OnSwapBuffersComplete(&ack); | |
| 1221 } | |
| 1222 | |
| 1223 virtual void AfterTest() OVERRIDE {} | |
| 1224 | |
| 1225 private: | |
| 1226 scoped_refptr<SolidColorLayer> solid_layer_; | |
| 1227 scoped_refptr<Layer> parent_layer_; | |
| 1228 scoped_refptr<TextureLayer> texture_layer_; | |
| 1229 | |
| 1230 // Used on the main thread. | |
| 1231 bool mailbox_changed_; | |
| 1232 TextureMailbox mailbox_; | |
| 1233 int mailbox_returned_; | |
| 1234 int prepare_called_; | |
| 1235 int commit_count_; | |
| 1236 }; | |
| 1237 | |
| 1238 SINGLE_AND_MULTI_THREAD_TEST_F(TextureLayerChangeInvisibleMailboxTest); | |
| 1239 | |
| 1240 // Test recovering from a lost context. | 902 // Test recovering from a lost context. |
| 1241 class TextureLayerLostContextTest | 903 class TextureLayerLostContextTest |
| 1242 : public LayerTreeTest, | 904 : public LayerTreeTest, |
| 1243 public TextureLayerClient { | 905 public TextureLayerClient { |
| 1244 public: | 906 public: |
| 1245 TextureLayerLostContextTest() | 907 TextureLayerLostContextTest() |
| 1246 : texture_(0), | 908 : texture_(0), |
| 1247 draw_count_(0) {} | 909 draw_count_(0) {} |
| 1248 | 910 |
| 1249 virtual scoped_ptr<OutputSurface> CreateOutputSurface(bool fallback) | 911 virtual scoped_ptr<OutputSurface> CreateOutputSurface(bool fallback) |
| (...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1450 int callback_count_; | 1112 int callback_count_; |
| 1451 scoped_refptr<Layer> root_; | 1113 scoped_refptr<Layer> root_; |
| 1452 scoped_refptr<TextureLayer> layer_; | 1114 scoped_refptr<TextureLayer> layer_; |
| 1453 }; | 1115 }; |
| 1454 | 1116 |
| 1455 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F( | 1117 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F( |
| 1456 TextureLayerWithMailboxImplThreadDeleted); | 1118 TextureLayerWithMailboxImplThreadDeleted); |
| 1457 | 1119 |
| 1458 } // namespace | 1120 } // namespace |
| 1459 } // namespace cc | 1121 } // namespace cc |
| OLD | NEW |