GPU workaround to simulate Out of Memory errors with large textures
[chromium-blink-merge.git] / cc / resources / video_resource_updater_unittest.cc
blob209835797600640229d56101291438cf72dfd45b
1 // Copyright 2013 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.
5 #include "cc/resources/video_resource_updater.h"
7 #include "base/memory/shared_memory.h"
8 #include "cc/resources/resource_provider.h"
9 #include "cc/test/fake_output_surface.h"
10 #include "cc/test/fake_output_surface_client.h"
11 #include "cc/test/test_shared_bitmap_manager.h"
12 #include "cc/test/test_web_graphics_context_3d.h"
13 #include "cc/trees/blocking_task_runner.h"
14 #include "media/base/video_frame.h"
15 #include "testing/gtest/include/gtest/gtest.h"
17 namespace cc {
18 namespace {
20 class WebGraphicsContext3DUploadCounter : public TestWebGraphicsContext3D {
21 public:
22 void texSubImage2D(GLenum target,
23 GLint level,
24 GLint xoffset,
25 GLint yoffset,
26 GLsizei width,
27 GLsizei height,
28 GLenum format,
29 GLenum type,
30 const void* pixels) override {
31 ++upload_count_;
34 int UploadCount() { return upload_count_; }
35 void ResetUploadCount() { upload_count_ = 0; }
37 private:
38 int upload_count_;
41 class SharedBitmapManagerAllocationCounter : public TestSharedBitmapManager {
42 public:
43 scoped_ptr<SharedBitmap> AllocateSharedBitmap(
44 const gfx::Size& size) override {
45 ++allocation_count_;
46 return TestSharedBitmapManager::AllocateSharedBitmap(size);
49 int AllocationCount() { return allocation_count_; }
50 void ResetAllocationCount() { allocation_count_ = 0; }
52 private:
53 int allocation_count_;
56 class VideoResourceUpdaterTest : public testing::Test {
57 protected:
58 VideoResourceUpdaterTest() {
59 scoped_ptr<WebGraphicsContext3DUploadCounter> context3d(
60 new WebGraphicsContext3DUploadCounter());
62 context3d_ = context3d.get();
64 output_surface3d_ =
65 FakeOutputSurface::Create3d(context3d.Pass());
66 CHECK(output_surface3d_->BindToClient(&client_));
68 output_surface_software_ = FakeOutputSurface::CreateSoftware(
69 make_scoped_ptr(new SoftwareOutputDevice));
70 CHECK(output_surface_software_->BindToClient(&client_));
72 shared_bitmap_manager_.reset(new SharedBitmapManagerAllocationCounter());
73 resource_provider3d_ =
74 ResourceProvider::Create(output_surface3d_.get(),
75 shared_bitmap_manager_.get(),
76 NULL,
77 NULL,
79 false,
80 1);
82 resource_provider_software_ = ResourceProvider::Create(
83 output_surface_software_.get(), shared_bitmap_manager_.get(), NULL,
84 NULL, 0, false, 1);
87 scoped_refptr<media::VideoFrame> CreateTestYUVVideoFrame() {
88 const int kDimension = 10;
89 gfx::Size size(kDimension, kDimension);
90 static uint8 y_data[kDimension * kDimension] = { 0 };
91 static uint8 u_data[kDimension * kDimension / 2] = { 0 };
92 static uint8 v_data[kDimension * kDimension / 2] = { 0 };
94 return media::VideoFrame::WrapExternalYuvData(
95 media::VideoFrame::YV16, // format
96 size, // coded_size
97 gfx::Rect(size), // visible_rect
98 size, // natural_size
99 size.width(), // y_stride
100 size.width() / 2, // u_stride
101 size.width() / 2, // v_stride
102 y_data, // y_data
103 u_data, // u_data
104 v_data, // v_data
105 base::TimeDelta(), // timestamp,
106 base::Closure()); // no_longer_needed_cb
109 WebGraphicsContext3DUploadCounter* context3d_;
110 FakeOutputSurfaceClient client_;
111 scoped_ptr<FakeOutputSurface> output_surface3d_;
112 scoped_ptr<FakeOutputSurface> output_surface_software_;
113 scoped_ptr<SharedBitmapManagerAllocationCounter> shared_bitmap_manager_;
114 scoped_ptr<ResourceProvider> resource_provider3d_;
115 scoped_ptr<ResourceProvider> resource_provider_software_;
118 TEST_F(VideoResourceUpdaterTest, SoftwareFrame) {
119 VideoResourceUpdater updater(output_surface3d_->context_provider(),
120 resource_provider3d_.get());
121 scoped_refptr<media::VideoFrame> video_frame = CreateTestYUVVideoFrame();
123 VideoFrameExternalResources resources =
124 updater.CreateExternalResourcesFromVideoFrame(video_frame);
125 EXPECT_EQ(VideoFrameExternalResources::YUV_RESOURCE, resources.type);
128 TEST_F(VideoResourceUpdaterTest, ReuseResource) {
129 VideoResourceUpdater updater(output_surface3d_->context_provider(),
130 resource_provider3d_.get());
131 scoped_refptr<media::VideoFrame> video_frame = CreateTestYUVVideoFrame();
132 video_frame->set_timestamp(base::TimeDelta::FromSeconds(1234));
134 // Allocate the resources for a YUV video frame.
135 context3d_->ResetUploadCount();
136 VideoFrameExternalResources resources =
137 updater.CreateExternalResourcesFromVideoFrame(video_frame);
138 EXPECT_EQ(VideoFrameExternalResources::YUV_RESOURCE, resources.type);
139 EXPECT_EQ(size_t(3), resources.mailboxes.size());
140 EXPECT_EQ(size_t(3), resources.release_callbacks.size());
141 EXPECT_EQ(size_t(0), resources.software_resources.size());
142 // Expect exactly three texture uploads, one for each plane.
143 EXPECT_EQ(3, context3d_->UploadCount());
145 // Simulate the ResourceProvider releasing the resources back to the video
146 // updater.
147 for (ReleaseCallbackImpl& release_callback : resources.release_callbacks)
148 release_callback.Run(0, false, nullptr);
150 // Allocate resources for the same frame.
151 context3d_->ResetUploadCount();
152 resources = updater.CreateExternalResourcesFromVideoFrame(video_frame);
153 EXPECT_EQ(VideoFrameExternalResources::YUV_RESOURCE, resources.type);
154 EXPECT_EQ(size_t(3), resources.mailboxes.size());
155 EXPECT_EQ(size_t(3), resources.release_callbacks.size());
156 // The data should be reused so expect no texture uploads.
157 EXPECT_EQ(0, context3d_->UploadCount());
160 TEST_F(VideoResourceUpdaterTest, ReuseResourceNoDelete) {
161 VideoResourceUpdater updater(output_surface3d_->context_provider(),
162 resource_provider3d_.get());
163 scoped_refptr<media::VideoFrame> video_frame = CreateTestYUVVideoFrame();
164 video_frame->set_timestamp(base::TimeDelta::FromSeconds(1234));
166 // Allocate the resources for a YUV video frame.
167 context3d_->ResetUploadCount();
168 VideoFrameExternalResources resources =
169 updater.CreateExternalResourcesFromVideoFrame(video_frame);
170 EXPECT_EQ(VideoFrameExternalResources::YUV_RESOURCE, resources.type);
171 EXPECT_EQ(size_t(3), resources.mailboxes.size());
172 EXPECT_EQ(size_t(3), resources.release_callbacks.size());
173 EXPECT_EQ(size_t(0), resources.software_resources.size());
174 // Expect exactly three texture uploads, one for each plane.
175 EXPECT_EQ(3, context3d_->UploadCount());
177 // Allocate resources for the same frame.
178 context3d_->ResetUploadCount();
179 resources = updater.CreateExternalResourcesFromVideoFrame(video_frame);
180 EXPECT_EQ(VideoFrameExternalResources::YUV_RESOURCE, resources.type);
181 EXPECT_EQ(size_t(3), resources.mailboxes.size());
182 EXPECT_EQ(size_t(3), resources.release_callbacks.size());
183 // The data should be reused so expect no texture uploads.
184 EXPECT_EQ(0, context3d_->UploadCount());
187 TEST_F(VideoResourceUpdaterTest, SoftwareFrameSoftwareCompositor) {
188 VideoResourceUpdater updater(nullptr, resource_provider_software_.get());
189 scoped_refptr<media::VideoFrame> video_frame = CreateTestYUVVideoFrame();
191 VideoFrameExternalResources resources =
192 updater.CreateExternalResourcesFromVideoFrame(video_frame);
193 EXPECT_EQ(VideoFrameExternalResources::SOFTWARE_RESOURCE, resources.type);
196 TEST_F(VideoResourceUpdaterTest, ReuseResourceSoftwareCompositor) {
197 VideoResourceUpdater updater(nullptr, resource_provider_software_.get());
198 scoped_refptr<media::VideoFrame> video_frame = CreateTestYUVVideoFrame();
199 video_frame->set_timestamp(base::TimeDelta::FromSeconds(1234));
201 // Allocate the resources for a software video frame.
202 shared_bitmap_manager_->ResetAllocationCount();
203 VideoFrameExternalResources resources =
204 updater.CreateExternalResourcesFromVideoFrame(video_frame);
205 EXPECT_EQ(VideoFrameExternalResources::SOFTWARE_RESOURCE, resources.type);
206 EXPECT_EQ(size_t(0), resources.mailboxes.size());
207 EXPECT_EQ(size_t(0), resources.release_callbacks.size());
208 EXPECT_EQ(size_t(1), resources.software_resources.size());
209 // Expect exactly one allocated shared bitmap.
210 EXPECT_EQ(1, shared_bitmap_manager_->AllocationCount());
212 // Simulate the ResourceProvider releasing the resource back to the video
213 // updater.
214 resources.software_release_callback.Run(0, false, nullptr);
216 // Allocate resources for the same frame.
217 shared_bitmap_manager_->ResetAllocationCount();
218 resources = updater.CreateExternalResourcesFromVideoFrame(video_frame);
219 EXPECT_EQ(VideoFrameExternalResources::SOFTWARE_RESOURCE, resources.type);
220 EXPECT_EQ(size_t(0), resources.mailboxes.size());
221 EXPECT_EQ(size_t(0), resources.release_callbacks.size());
222 EXPECT_EQ(size_t(1), resources.software_resources.size());
223 // The data should be reused so expect no new allocations.
224 EXPECT_EQ(0, shared_bitmap_manager_->AllocationCount());
227 TEST_F(VideoResourceUpdaterTest, ReuseResourceNoDeleteSoftwareCompositor) {
228 VideoResourceUpdater updater(nullptr, resource_provider_software_.get());
229 scoped_refptr<media::VideoFrame> video_frame = CreateTestYUVVideoFrame();
230 video_frame->set_timestamp(base::TimeDelta::FromSeconds(1234));
232 // Allocate the resources for a software video frame.
233 shared_bitmap_manager_->ResetAllocationCount();
234 VideoFrameExternalResources resources =
235 updater.CreateExternalResourcesFromVideoFrame(video_frame);
236 EXPECT_EQ(VideoFrameExternalResources::SOFTWARE_RESOURCE, resources.type);
237 EXPECT_EQ(size_t(0), resources.mailboxes.size());
238 EXPECT_EQ(size_t(0), resources.release_callbacks.size());
239 EXPECT_EQ(size_t(1), resources.software_resources.size());
240 // Expect exactly one allocated shared bitmap.
241 EXPECT_EQ(1, shared_bitmap_manager_->AllocationCount());
243 // Allocate resources for the same frame.
244 shared_bitmap_manager_->ResetAllocationCount();
245 resources = updater.CreateExternalResourcesFromVideoFrame(video_frame);
246 EXPECT_EQ(VideoFrameExternalResources::SOFTWARE_RESOURCE, resources.type);
247 EXPECT_EQ(size_t(0), resources.mailboxes.size());
248 EXPECT_EQ(size_t(0), resources.release_callbacks.size());
249 EXPECT_EQ(size_t(1), resources.software_resources.size());
250 // The data should be reused so expect no new allocations.
251 EXPECT_EQ(0, shared_bitmap_manager_->AllocationCount());
254 } // namespace
255 } // namespace cc