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 |