Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(588)

Side by Side Diff: cc/resources/resource_provider_unittest.cc

Issue 2945673002: Allow creating GLImage-backed textures with glTexStorage2D. (Closed)
Patch Set: fix unittests Created 3 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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/resources/resource_provider.h" 5 #include "cc/resources/resource_provider.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 #include <stdint.h> 8 #include <stdint.h>
9 9
10 #include <algorithm> 10 #include <algorithm>
(...skipping 24 matching lines...) Expand all
35 #include "third_party/khronos/GLES2/gl2.h" 35 #include "third_party/khronos/GLES2/gl2.h"
36 #include "third_party/khronos/GLES2/gl2ext.h" 36 #include "third_party/khronos/GLES2/gl2ext.h"
37 #include "ui/gfx/geometry/rect.h" 37 #include "ui/gfx/geometry/rect.h"
38 #include "ui/gfx/gpu_memory_buffer.h" 38 #include "ui/gfx/gpu_memory_buffer.h"
39 39
40 using testing::Mock; 40 using testing::Mock;
41 using testing::NiceMock; 41 using testing::NiceMock;
42 using testing::Return; 42 using testing::Return;
43 using testing::StrictMock; 43 using testing::StrictMock;
44 using testing::_; 44 using testing::_;
45 using testing::AnyNumber;
45 46
46 namespace cc { 47 namespace cc {
47 namespace { 48 namespace {
48 49
49 static const bool kUseGpuMemoryBufferResources = false; 50 static const bool kUseGpuMemoryBufferResources = false;
50 static const bool kEnableColorCorrectRendering = false; 51 static const bool kEnableColorCorrectRendering = false;
51 static const bool kDelegatedSyncPointsRequired = true; 52 static const bool kDelegatedSyncPointsRequired = true;
52 53
53 MATCHER_P(MatchesSyncToken, sync_token, "") { 54 MATCHER_P(MatchesSyncToken, sync_token, "") {
54 gpu::SyncToken other; 55 gpu::SyncToken other;
(...skipping 380 matching lines...) Expand 10 before | Expand all | Expand 10 after
435 : shared_data_(ContextSharedData::Create()), 436 : shared_data_(ContextSharedData::Create()),
436 context3d_(NULL), 437 context3d_(NULL),
437 child_context_(NULL), 438 child_context_(NULL),
438 main_thread_task_runner_(BlockingTaskRunner::Create(NULL)) { 439 main_thread_task_runner_(BlockingTaskRunner::Create(NULL)) {
439 switch (GetParam()) { 440 switch (GetParam()) {
440 case ResourceProvider::RESOURCE_TYPE_GPU_MEMORY_BUFFER: 441 case ResourceProvider::RESOURCE_TYPE_GPU_MEMORY_BUFFER:
441 case ResourceProvider::RESOURCE_TYPE_GL_TEXTURE: { 442 case ResourceProvider::RESOURCE_TYPE_GL_TEXTURE: {
442 std::unique_ptr<ResourceProviderContext> context3d( 443 std::unique_ptr<ResourceProviderContext> context3d(
443 ResourceProviderContext::Create(shared_data_.get())); 444 ResourceProviderContext::Create(shared_data_.get()));
444 context3d_ = context3d.get(); 445 context3d_ = context3d.get();
446 context3d_->set_support_texture_buffer_chromium(true);
445 context_provider_ = TestContextProvider::Create(std::move(context3d)); 447 context_provider_ = TestContextProvider::Create(std::move(context3d));
446 context_provider_->BindToCurrentThread(); 448 context_provider_->BindToCurrentThread();
447 449
448 std::unique_ptr<ResourceProviderContext> child_context_owned = 450 std::unique_ptr<ResourceProviderContext> child_context_owned =
449 ResourceProviderContext::Create(shared_data_.get()); 451 ResourceProviderContext::Create(shared_data_.get());
450 child_context_ = child_context_owned.get(); 452 child_context_ = child_context_owned.get();
451 child_context_provider_ = 453 child_context_provider_ =
452 TestContextProvider::Create(std::move(child_context_owned)); 454 TestContextProvider::Create(std::move(child_context_owned));
453 child_context_provider_->BindToCurrentThread(); 455 child_context_provider_->BindToCurrentThread();
454 break; 456 break;
(...skipping 2988 matching lines...) Expand 10 before | Expand all | Expand 10 after
3443 GLsizei height, 3445 GLsizei height,
3444 GLint border, 3446 GLint border,
3445 GLsizei image_size, 3447 GLsizei image_size,
3446 const void* data)); 3448 const void* data));
3447 MOCK_METHOD1(waitAsyncTexImage2DCHROMIUM, void(GLenum)); 3449 MOCK_METHOD1(waitAsyncTexImage2DCHROMIUM, void(GLenum));
3448 MOCK_METHOD4(createImageCHROMIUM, 3450 MOCK_METHOD4(createImageCHROMIUM,
3449 GLuint(ClientBuffer, GLsizei, GLsizei, GLenum)); 3451 GLuint(ClientBuffer, GLsizei, GLsizei, GLenum));
3450 MOCK_METHOD1(destroyImageCHROMIUM, void(GLuint)); 3452 MOCK_METHOD1(destroyImageCHROMIUM, void(GLuint));
3451 MOCK_METHOD2(bindTexImage2DCHROMIUM, void(GLenum, GLint)); 3453 MOCK_METHOD2(bindTexImage2DCHROMIUM, void(GLenum, GLint));
3452 MOCK_METHOD2(releaseTexImage2DCHROMIUM, void(GLenum, GLint)); 3454 MOCK_METHOD2(releaseTexImage2DCHROMIUM, void(GLenum, GLint));
3453 3455 MOCK_METHOD3(texParameteri, void(GLenum target, GLenum pname, GLint param));
3454 // We're mocking bindTexture, so we override
3455 // TestWebGraphicsContext3D::texParameteri to avoid assertions related to the
3456 // currently bound texture.
3457 virtual void texParameteri(GLenum target, GLenum pname, GLint param) {}
3458 }; 3456 };
3459 3457
3460 TEST_P(ResourceProviderTest, TextureAllocation) { 3458 TEST_P(ResourceProviderTest, TextureAllocation) {
3461 // Only for GL textures. 3459 // Only for GL textures.
3462 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) 3460 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
3463 return; 3461 return;
3464 std::unique_ptr<AllocationTrackingContext3D> context_owned( 3462 std::unique_ptr<AllocationTrackingContext3D> context_owned(
3465 new StrictMock<AllocationTrackingContext3D>); 3463 new StrictMock<AllocationTrackingContext3D>);
3466 AllocationTrackingContext3D* context = context_owned.get(); 3464 AllocationTrackingContext3D* context = context_owned.get();
3467 auto context_provider = TestContextProvider::Create(std::move(context_owned)); 3465 auto context_provider = TestContextProvider::Create(std::move(context_owned));
3468 context_provider->BindToCurrentThread(); 3466 context_provider->BindToCurrentThread();
3469 3467
3470 std::unique_ptr<ResourceProvider> resource_provider( 3468 std::unique_ptr<ResourceProvider> resource_provider(
3471 base::MakeUnique<ResourceProvider>( 3469 base::MakeUnique<ResourceProvider>(
3472 context_provider.get(), shared_bitmap_manager_.get(), 3470 context_provider.get(), shared_bitmap_manager_.get(),
3473 gpu_memory_buffer_manager_.get(), nullptr, 3471 gpu_memory_buffer_manager_.get(), nullptr,
3474 kDelegatedSyncPointsRequired, kEnableColorCorrectRendering, 3472 kDelegatedSyncPointsRequired, kEnableColorCorrectRendering,
3475 CreateResourceSettings())); 3473 CreateResourceSettings()));
3476 3474
3477 gfx::Size size(2, 2); 3475 gfx::Size size(2, 2);
3478 gfx::Vector2d offset(0, 0); 3476 gfx::Vector2d offset(0, 0);
3479 viz::ResourceFormat format = viz::RGBA_8888; 3477 viz::ResourceFormat format = viz::RGBA_8888;
3480 viz::ResourceId id = 0; 3478 viz::ResourceId id = 0;
3481 uint8_t pixels[16] = { 0 }; 3479 uint8_t pixels[16] = { 0 };
3482 int texture_id = 123; 3480 int texture_id = 123;
3483 3481
3482 EXPECT_CALL(*context, texParameteri(_, _, _)).Times(AnyNumber());
3484 // Lazy allocation. Don't allocate when creating the resource. 3483 // Lazy allocation. Don't allocate when creating the resource.
3485 id = resource_provider->CreateResource( 3484 id = resource_provider->CreateResource(
3486 size, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format, 3485 size, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format,
3487 gfx::ColorSpace()); 3486 gfx::ColorSpace());
3488 3487
3489 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id)); 3488 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
3490 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(1); 3489 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(1);
3491 resource_provider->CreateForTesting(id); 3490 resource_provider->CreateForTesting(id);
3492 3491
3493 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1); 3492 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
3494 resource_provider->DeleteResource(id); 3493 resource_provider->DeleteResource(id);
3495 3494
3496 Mock::VerifyAndClearExpectations(context); 3495 Mock::VerifyAndClearExpectations(context);
3496 EXPECT_CALL(*context, texParameteri(_, _, _)).Times(AnyNumber());
3497 3497
3498 // Do allocate when we set the pixels. 3498 // Do allocate when we set the pixels.
3499 id = resource_provider->CreateResource( 3499 id = resource_provider->CreateResource(
3500 size, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format, 3500 size, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format,
3501 gfx::ColorSpace()); 3501 gfx::ColorSpace());
3502 3502
3503 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id)); 3503 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
3504 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(3); 3504 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(3);
3505 EXPECT_CALL(*context, texImage2D(_, _, _, 2, 2, _, _, _, _)).Times(1); 3505 EXPECT_CALL(*context, texImage2D(_, _, _, 2, 2, _, _, _, _)).Times(1);
3506 EXPECT_CALL(*context, texSubImage2D(_, _, _, _, 2, 2, _, _, _)).Times(1); 3506 EXPECT_CALL(*context, texSubImage2D(_, _, _, _, 2, 2, _, _, _)).Times(1);
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
3550 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id)); 3550 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
3551 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2); 3551 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2);
3552 bool is_immutable_hint = 3552 bool is_immutable_hint =
3553 hints[texture_id - 1] & ResourceProvider::TEXTURE_HINT_IMMUTABLE; 3553 hints[texture_id - 1] & ResourceProvider::TEXTURE_HINT_IMMUTABLE;
3554 bool support_immutable_texture = 3554 bool support_immutable_texture =
3555 is_immutable_hint && formats[i] != viz::BGRA_8888; 3555 is_immutable_hint && formats[i] != viz::BGRA_8888;
3556 EXPECT_CALL(*context, texStorage2DEXT(_, _, _, 2, 2)) 3556 EXPECT_CALL(*context, texStorage2DEXT(_, _, _, 2, 2))
3557 .Times(support_immutable_texture ? 1 : 0); 3557 .Times(support_immutable_texture ? 1 : 0);
3558 EXPECT_CALL(*context, texImage2D(_, _, _, 2, 2, _, _, _, _)) 3558 EXPECT_CALL(*context, texImage2D(_, _, _, 2, 2, _, _, _, _))
3559 .Times(support_immutable_texture ? 0 : 1); 3559 .Times(support_immutable_texture ? 0 : 1);
3560 EXPECT_CALL(*context, texParameteri(_, _, _)).Times(AnyNumber());
3560 resource_provider->AllocateForTesting(id); 3561 resource_provider->AllocateForTesting(id);
3561 3562
3562 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1); 3563 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
3563 resource_provider->DeleteResource(id); 3564 resource_provider->DeleteResource(id);
3564 3565
3565 Mock::VerifyAndClearExpectations(context); 3566 Mock::VerifyAndClearExpectations(context);
3566 } 3567 }
3567 } 3568 }
3568 } 3569 }
3569 3570
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
3603 size, hints[texture_id - 1], formats[i], gfx::ColorSpace()); 3604 size, hints[texture_id - 1], formats[i], gfx::ColorSpace());
3604 3605
3605 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id)); 3606 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
3606 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2); 3607 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2);
3607 bool is_immutable_hint = 3608 bool is_immutable_hint =
3608 hints[texture_id - 1] & ResourceProvider::TEXTURE_HINT_IMMUTABLE; 3609 hints[texture_id - 1] & ResourceProvider::TEXTURE_HINT_IMMUTABLE;
3609 EXPECT_CALL(*context, texStorage2DEXT(_, _, _, 2, 2)) 3610 EXPECT_CALL(*context, texStorage2DEXT(_, _, _, 2, 2))
3610 .Times(is_immutable_hint ? 1 : 0); 3611 .Times(is_immutable_hint ? 1 : 0);
3611 EXPECT_CALL(*context, texImage2D(_, _, _, 2, 2, _, _, _, _)) 3612 EXPECT_CALL(*context, texImage2D(_, _, _, 2, 2, _, _, _, _))
3612 .Times(is_immutable_hint ? 0 : 1); 3613 .Times(is_immutable_hint ? 0 : 1);
3614 EXPECT_CALL(*context, texParameteri(_, _, _)).Times(AnyNumber());
3615 resource_provider->AllocateForTesting(id);
3616
3617 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
3618 resource_provider->DeleteResource(id);
3619
3620 Mock::VerifyAndClearExpectations(context);
3621 }
3622 }
3623 }
3624
3625 TEST_P(ResourceProviderTest, ImageTextureAllocationHint_BGRA) {
3626 // Only for GL textures.
3627 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GPU_MEMORY_BUFFER)
3628 return;
3629 std::unique_ptr<AllocationTrackingContext3D> context_owned(
3630 new StrictMock<AllocationTrackingContext3D>);
3631 AllocationTrackingContext3D* context = context_owned.get();
3632 context->set_support_texture_format_bgra8888(true);
3633 context->set_support_texture_storage(true);
3634 context->set_support_texture_usage(true);
3635 auto context_provider = TestContextProvider::Create(std::move(context_owned));
3636 context_provider->BindToCurrentThread();
3637
3638 std::unique_ptr<ResourceProvider> resource_provider(
3639 base::MakeUnique<ResourceProvider>(
3640 context_provider.get(), shared_bitmap_manager_.get(),
3641 gpu_memory_buffer_manager_.get(), nullptr,
3642 kDelegatedSyncPointsRequired, kEnableColorCorrectRendering,
3643 CreateResourceSettings()));
3644
3645 gfx::Size size(2, 2);
3646 const viz::ResourceFormat formats[2] = {viz::RGBA_8888, viz::BGRA_8888};
3647
3648 const ResourceProvider::TextureHint hints[4] = {
3649 ResourceProvider::TEXTURE_HINT_DEFAULT,
3650 ResourceProvider::TEXTURE_HINT_IMMUTABLE,
3651 ResourceProvider::TEXTURE_HINT_FRAMEBUFFER,
3652 ResourceProvider::TEXTURE_HINT_IMMUTABLE_FRAMEBUFFER,
3653 };
3654 for (size_t i = 0; i < arraysize(formats); ++i) {
3655 for (GLuint texture_id = 1; texture_id <= arraysize(hints); ++texture_id) {
3656 // Lazy allocation. Don't allocate when creating the resource.
3657 viz::ResourceId id = resource_provider->CreateResource(
3658 size, hints[texture_id - 1], formats[i], gfx::ColorSpace());
3659
3660 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
3661 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2);
3662 bool is_immutable_hint =
3663 hints[texture_id - 1] & ResourceProvider::TEXTURE_HINT_IMMUTABLE;
3664 EXPECT_CALL(*context, texParameteri(_, GL_TEXTURE_BUFFER_USAGE_CHROMIUM,
3665 GL_TEXTURE_BUFFER_SCANOUT_CHROMIUM));
3666 EXPECT_CALL(*context, texStorage2DEXT(_, _, _, 2, 2))
3667 .Times(is_immutable_hint ? 1 : 0);
3668 EXPECT_CALL(*context, texImage2D(_, _, _, 2, 2, _, _, _, _))
3669 .Times(is_immutable_hint ? 0 : 1);
3613 resource_provider->AllocateForTesting(id); 3670 resource_provider->AllocateForTesting(id);
3614 3671
3615 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1); 3672 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
3616 resource_provider->DeleteResource(id); 3673 resource_provider->DeleteResource(id);
3617 3674
3618 Mock::VerifyAndClearExpectations(context); 3675 Mock::VerifyAndClearExpectations(context);
3619 } 3676 }
3620 } 3677 }
3621 } 3678 }
3622 3679
(...skipping 15 matching lines...) Expand all
3638 const unsigned kTextureId = 123u; 3695 const unsigned kTextureId = 123u;
3639 const unsigned kImageId = 234u; 3696 const unsigned kImageId = 234u;
3640 3697
3641 std::unique_ptr<ResourceProvider> resource_provider( 3698 std::unique_ptr<ResourceProvider> resource_provider(
3642 base::MakeUnique<ResourceProvider>( 3699 base::MakeUnique<ResourceProvider>(
3643 context_provider.get(), shared_bitmap_manager_.get(), 3700 context_provider.get(), shared_bitmap_manager_.get(),
3644 gpu_memory_buffer_manager_.get(), nullptr, 3701 gpu_memory_buffer_manager_.get(), nullptr,
3645 kDelegatedSyncPointsRequired, kEnableColorCorrectRendering, 3702 kDelegatedSyncPointsRequired, kEnableColorCorrectRendering,
3646 CreateResourceSettings())); 3703 CreateResourceSettings()));
3647 3704
3705 EXPECT_CALL(*context, texParameteri(_, _, _)).Times(AnyNumber());
3648 id = resource_provider->CreateResource( 3706 id = resource_provider->CreateResource(
3649 size, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format, 3707 size, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format,
3650 gfx::ColorSpace()); 3708 gfx::ColorSpace());
3651 3709
3652 EXPECT_CALL(*context, NextTextureId()) 3710 EXPECT_CALL(*context, NextTextureId())
3653 .WillOnce(Return(kTextureId)) 3711 .WillOnce(Return(kTextureId))
3654 .RetiresOnSaturation(); 3712 .RetiresOnSaturation();
3655 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kTextureId)) 3713 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kTextureId))
3656 .Times(3) 3714 .Times(3)
3657 .RetiresOnSaturation(); 3715 .RetiresOnSaturation();
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
3723 kDelegatedSyncPointsRequired, kEnableColorCorrectRendering, 3781 kDelegatedSyncPointsRequired, kEnableColorCorrectRendering,
3724 CreateResourceSettings())); 3782 CreateResourceSettings()));
3725 int texture_id = 123; 3783 int texture_id = 123;
3726 3784
3727 viz::ResourceId id = resource_provider->CreateResource( 3785 viz::ResourceId id = resource_provider->CreateResource(
3728 size, ResourceProvider::TEXTURE_HINT_IMMUTABLE, viz::ETC1, 3786 size, ResourceProvider::TEXTURE_HINT_IMMUTABLE, viz::ETC1,
3729 gfx::ColorSpace()); 3787 gfx::ColorSpace());
3730 EXPECT_NE(0u, id); 3788 EXPECT_NE(0u, id);
3731 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id)); 3789 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
3732 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2); 3790 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2);
3791 EXPECT_CALL(*context, texParameteri(_, _, _)).Times(AnyNumber());
3733 resource_provider->AllocateForTesting(id); 3792 resource_provider->AllocateForTesting(id);
3734 3793
3735 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1); 3794 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
3736 resource_provider->DeleteResource(id); 3795 resource_provider->DeleteResource(id);
3737 } 3796 }
3738 3797
3739 TEST_P(ResourceProviderTest, CompressedTextureETC1Upload) { 3798 TEST_P(ResourceProviderTest, CompressedTextureETC1Upload) {
3740 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) 3799 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
3741 return; 3800 return;
3742 3801
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after
3864 lock.set_sync_token(token); 3923 lock.set_sync_token(token);
3865 } 3924 }
3866 3925
3867 gpu::SyncToken last_token = 3926 gpu::SyncToken last_token =
3868 resource_provider_->GetSyncTokenForResources(array); 3927 resource_provider_->GetSyncTokenForResources(array);
3869 EXPECT_EQ(last_token.release_count(), 10u); 3928 EXPECT_EQ(last_token.release_count(), 10u);
3870 } 3929 }
3871 3930
3872 } // namespace 3931 } // namespace
3873 } // namespace cc 3932 } // namespace cc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698