OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 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 | 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/video_resource_updater.h" | 5 #include "cc/resources/video_resource_updater.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/debug/trace_event.h" | 8 #include "base/debug/trace_event.h" |
9 #include "cc/output/gl_renderer.h" | 9 #include "cc/output/gl_renderer.h" |
10 #include "cc/resources/resource_provider.h" | 10 #include "cc/resources/resource_provider.h" |
11 #include "gpu/GLES2/gl2extchromium.h" | 11 #include "gpu/GLES2/gl2extchromium.h" |
12 #include "gpu/command_buffer/client/gles2_interface.h" | 12 #include "gpu/command_buffer/client/gles2_interface.h" |
13 #include "media/base/video_frame.h" | 13 #include "media/base/video_frame.h" |
14 #include "media/filters/skcanvas_video_renderer.h" | 14 #include "media/filters/skcanvas_video_renderer.h" |
15 #include "third_party/khronos/GLES2/gl2.h" | 15 #include "third_party/khronos/GLES2/gl2.h" |
16 #include "third_party/khronos/GLES2/gl2ext.h" | 16 #include "third_party/khronos/GLES2/gl2ext.h" |
17 #include "ui/gfx/geometry/size_conversions.h" | 17 #include "ui/gfx/geometry/size_conversions.h" |
18 | 18 |
19 namespace cc { | 19 namespace cc { |
20 | 20 |
21 namespace { | 21 namespace { |
22 | 22 |
23 const ResourceFormat kYUVResourceFormat = LUMINANCE_8; | |
24 const ResourceFormat kRGBResourceFormat = RGBA_8888; | 23 const ResourceFormat kRGBResourceFormat = RGBA_8888; |
25 | 24 |
26 class SyncPointClientImpl : public media::VideoFrame::SyncPointClient { | 25 class SyncPointClientImpl : public media::VideoFrame::SyncPointClient { |
27 public: | 26 public: |
28 explicit SyncPointClientImpl(gpu::gles2::GLES2Interface* gl) : gl_(gl) {} | 27 explicit SyncPointClientImpl(gpu::gles2::GLES2Interface* gl) : gl_(gl) {} |
29 ~SyncPointClientImpl() override {} | 28 ~SyncPointClientImpl() override {} |
30 uint32 InsertSyncPoint() override { | 29 uint32 InsertSyncPoint() override { |
31 return GLC(gl_, gl_->InsertSyncPointCHROMIUM()); | 30 return GLC(gl_, gl_->InsertSyncPointCHROMIUM()); |
32 } | 31 } |
33 void WaitSyncPoint(uint32 sync_point) override { | 32 void WaitSyncPoint(uint32 sync_point) override { |
34 GLC(gl_, gl_->WaitSyncPointCHROMIUM(sync_point)); | 33 GLC(gl_, gl_->WaitSyncPointCHROMIUM(sync_point)); |
35 } | 34 } |
36 | 35 |
37 private: | 36 private: |
38 gpu::gles2::GLES2Interface* gl_; | 37 gpu::gles2::GLES2Interface* gl_; |
39 }; | 38 }; |
40 | 39 |
41 } // namespace | 40 } // namespace |
42 | 41 |
| 42 VideoResourceUpdater::PlaneResource::PlaneResource( |
| 43 unsigned int resource_id, |
| 44 const gfx::Size& resource_size, |
| 45 ResourceFormat resource_format, |
| 46 gpu::Mailbox mailbox) |
| 47 : resource_id(resource_id), |
| 48 resource_size(resource_size), |
| 49 resource_format(resource_format), |
| 50 mailbox(mailbox), |
| 51 frame_ptr(nullptr), |
| 52 plane_index(0) { |
| 53 } |
| 54 |
| 55 bool VideoResourceUpdater::PlaneResourceMatchesUniqueID( |
| 56 const PlaneResource& plane_resource, |
| 57 const media::VideoFrame* video_frame, |
| 58 int plane_index) { |
| 59 return plane_resource.frame_ptr == video_frame && |
| 60 plane_resource.plane_index == plane_index && |
| 61 plane_resource.timestamp == video_frame->timestamp(); |
| 62 } |
| 63 |
| 64 void VideoResourceUpdater::SetPlaneResourceUniqueId( |
| 65 const media::VideoFrame* video_frame, |
| 66 int plane_index, |
| 67 PlaneResource* plane_resource) { |
| 68 plane_resource->frame_ptr = video_frame; |
| 69 plane_resource->plane_index = plane_index; |
| 70 plane_resource->timestamp = video_frame->timestamp(); |
| 71 } |
| 72 |
43 VideoFrameExternalResources::VideoFrameExternalResources() : type(NONE) {} | 73 VideoFrameExternalResources::VideoFrameExternalResources() : type(NONE) {} |
44 | 74 |
45 VideoFrameExternalResources::~VideoFrameExternalResources() {} | 75 VideoFrameExternalResources::~VideoFrameExternalResources() {} |
46 | 76 |
47 VideoResourceUpdater::VideoResourceUpdater(ContextProvider* context_provider, | 77 VideoResourceUpdater::VideoResourceUpdater(ContextProvider* context_provider, |
48 ResourceProvider* resource_provider) | 78 ResourceProvider* resource_provider) |
49 : context_provider_(context_provider), | 79 : context_provider_(context_provider), |
50 resource_provider_(resource_provider) { | 80 resource_provider_(resource_provider) { |
51 } | 81 } |
52 | 82 |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
97 case media::VideoFrame::NV12: | 127 case media::VideoFrame::NV12: |
98 break; | 128 break; |
99 } | 129 } |
100 return false; | 130 return false; |
101 } | 131 } |
102 | 132 |
103 // For frames that we receive in software format, determine the dimensions of | 133 // For frames that we receive in software format, determine the dimensions of |
104 // each plane in the frame. | 134 // each plane in the frame. |
105 static gfx::Size SoftwarePlaneDimension( | 135 static gfx::Size SoftwarePlaneDimension( |
106 const scoped_refptr<media::VideoFrame>& input_frame, | 136 const scoped_refptr<media::VideoFrame>& input_frame, |
107 ResourceFormat output_resource_format, | 137 bool software_compositor, |
108 size_t plane_index) { | 138 size_t plane_index) { |
109 if (output_resource_format == kYUVResourceFormat) { | 139 if (!software_compositor) { |
110 return media::VideoFrame::PlaneSize( | 140 return media::VideoFrame::PlaneSize( |
111 input_frame->format(), plane_index, input_frame->coded_size()); | 141 input_frame->format(), plane_index, input_frame->coded_size()); |
112 } | 142 } |
113 | |
114 DCHECK_EQ(output_resource_format, kRGBResourceFormat); | |
115 return input_frame->coded_size(); | 143 return input_frame->coded_size(); |
116 } | 144 } |
117 | 145 |
118 VideoFrameExternalResources VideoResourceUpdater::CreateForSoftwarePlanes( | 146 VideoFrameExternalResources VideoResourceUpdater::CreateForSoftwarePlanes( |
119 const scoped_refptr<media::VideoFrame>& video_frame) { | 147 const scoped_refptr<media::VideoFrame>& video_frame) { |
120 TRACE_EVENT0("cc", "VideoResourceUpdater::CreateForSoftwarePlanes"); | 148 TRACE_EVENT0("cc", "VideoResourceUpdater::CreateForSoftwarePlanes"); |
121 media::VideoFrame::Format input_frame_format = video_frame->format(); | 149 media::VideoFrame::Format input_frame_format = video_frame->format(); |
122 | 150 |
123 #if defined(VIDEO_HOLE) | 151 #if defined(VIDEO_HOLE) |
124 if (input_frame_format == media::VideoFrame::HOLE) { | 152 if (input_frame_format == media::VideoFrame::HOLE) { |
(...skipping 13 matching lines...) Expand all Loading... |
138 if (input_frame_format != media::VideoFrame::YV12 && | 166 if (input_frame_format != media::VideoFrame::YV12 && |
139 input_frame_format != media::VideoFrame::I420 && | 167 input_frame_format != media::VideoFrame::I420 && |
140 input_frame_format != media::VideoFrame::YV12A && | 168 input_frame_format != media::VideoFrame::YV12A && |
141 input_frame_format != media::VideoFrame::YV12J && | 169 input_frame_format != media::VideoFrame::YV12J && |
142 input_frame_format != media::VideoFrame::YV16 && | 170 input_frame_format != media::VideoFrame::YV16 && |
143 input_frame_format != media::VideoFrame::YV24) | 171 input_frame_format != media::VideoFrame::YV24) |
144 return VideoFrameExternalResources(); | 172 return VideoFrameExternalResources(); |
145 | 173 |
146 bool software_compositor = context_provider_ == NULL; | 174 bool software_compositor = context_provider_ == NULL; |
147 | 175 |
148 ResourceFormat output_resource_format = kYUVResourceFormat; | 176 ResourceFormat output_resource_format = |
| 177 resource_provider_->yuv_resource_format(); |
149 size_t output_plane_count = media::VideoFrame::NumPlanes(input_frame_format); | 178 size_t output_plane_count = media::VideoFrame::NumPlanes(input_frame_format); |
150 | 179 |
151 // TODO(skaslev): If we're in software compositing mode, we do the YUV -> RGB | 180 // TODO(skaslev): If we're in software compositing mode, we do the YUV -> RGB |
152 // conversion here. That involves an extra copy of each frame to a bitmap. | 181 // conversion here. That involves an extra copy of each frame to a bitmap. |
153 // Obviously, this is suboptimal and should be addressed once ubercompositor | 182 // Obviously, this is suboptimal and should be addressed once ubercompositor |
154 // starts shaping up. | 183 // starts shaping up. |
155 if (software_compositor) { | 184 if (software_compositor) { |
156 output_resource_format = kRGBResourceFormat; | 185 output_resource_format = kRGBResourceFormat; |
157 output_plane_count = 1; | 186 output_plane_count = 1; |
158 } | 187 } |
159 | 188 |
160 int max_resource_size = resource_provider_->max_texture_size(); | 189 int max_resource_size = resource_provider_->max_texture_size(); |
161 std::vector<PlaneResource> plane_resources; | 190 std::vector<PlaneResource> plane_resources; |
162 bool allocation_success = true; | 191 bool allocation_success = true; |
163 | 192 |
164 for (size_t i = 0; i < output_plane_count; ++i) { | 193 for (size_t i = 0; i < output_plane_count; ++i) { |
165 gfx::Size output_plane_resource_size = | 194 gfx::Size output_plane_resource_size = |
166 SoftwarePlaneDimension(video_frame, output_resource_format, i); | 195 SoftwarePlaneDimension(video_frame, software_compositor, i); |
167 if (output_plane_resource_size.IsEmpty() || | 196 if (output_plane_resource_size.IsEmpty() || |
168 output_plane_resource_size.width() > max_resource_size || | 197 output_plane_resource_size.width() > max_resource_size || |
169 output_plane_resource_size.height() > max_resource_size) { | 198 output_plane_resource_size.height() > max_resource_size) { |
170 allocation_success = false; | 199 allocation_success = false; |
171 break; | 200 break; |
172 } | 201 } |
173 | 202 |
174 ResourceProvider::ResourceId resource_id = 0; | |
175 gpu::Mailbox mailbox; | |
176 | |
177 // Try recycle a previously-allocated resource. | 203 // Try recycle a previously-allocated resource. |
178 for (size_t i = 0; i < recycled_resources_.size(); ++i) { | 204 auto recycled_it = recycled_resources_.end(); |
179 bool resource_matches = | 205 for (auto it = recycled_resources_.begin(); it != recycled_resources_.end(); |
180 recycled_resources_[i].resource_format == output_resource_format && | 206 ++it) { |
181 recycled_resources_[i].resource_size == output_plane_resource_size; | 207 const bool resource_matches = |
182 bool not_in_use = | 208 it->resource_format == output_resource_format && |
183 !software_compositor || !resource_provider_->InUseByConsumer( | 209 it->resource_size == output_plane_resource_size; |
184 recycled_resources_[i].resource_id); | 210 const bool in_use = software_compositor && |
185 if (resource_matches && not_in_use) { | 211 resource_provider_->InUseByConsumer(it->resource_id); |
186 resource_id = recycled_resources_[i].resource_id; | 212 if (resource_matches && !in_use) { |
187 mailbox = recycled_resources_[i].mailbox; | 213 // We found a recycled resource with the allocation size and format we |
188 recycled_resources_.erase(recycled_resources_.begin() + i); | 214 // are looking for. |
189 break; | 215 recycled_it = it; |
| 216 // Keep looking for a recycled resource that also contains the data we |
| 217 // are planning to put in it. |
| 218 if (PlaneResourceMatchesUniqueID(*it, video_frame.get(), i)) |
| 219 break; |
190 } | 220 } |
191 } | 221 } |
192 | 222 |
193 if (resource_id == 0) { | 223 // Check if we can avoid allocating a new resource. |
194 // TODO(danakj): Abstract out hw/sw resource create/delete from | 224 if (recycled_it != recycled_resources_.end()) { |
195 // ResourceProvider and stop using ResourceProvider in this class. | 225 plane_resources.push_back(*recycled_it); |
196 resource_id = resource_provider_->CreateResource( | 226 recycled_resources_.erase(recycled_it); |
197 output_plane_resource_size, | 227 continue; |
198 GL_CLAMP_TO_EDGE, | |
199 ResourceProvider::TextureHintImmutable, | |
200 output_resource_format); | |
201 | |
202 DCHECK(mailbox.IsZero()); | |
203 | |
204 if (!software_compositor) { | |
205 DCHECK(context_provider_); | |
206 | |
207 gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL(); | |
208 | |
209 GLC(gl, gl->GenMailboxCHROMIUM(mailbox.name)); | |
210 ResourceProvider::ScopedWriteLockGL lock(resource_provider_, | |
211 resource_id); | |
212 GLC(gl, | |
213 gl->ProduceTextureDirectCHROMIUM( | |
214 lock.texture_id(), GL_TEXTURE_2D, mailbox.name)); | |
215 } | |
216 | |
217 if (resource_id) | |
218 all_resources_.push_back(resource_id); | |
219 } | 228 } |
220 | 229 |
| 230 // TODO(danakj): Abstract out hw/sw resource create/delete from |
| 231 // ResourceProvider and stop using ResourceProvider in this class. |
| 232 const ResourceProvider::ResourceId resource_id = |
| 233 resource_provider_->CreateResource( |
| 234 output_plane_resource_size, GL_CLAMP_TO_EDGE, |
| 235 ResourceProvider::TextureHintImmutable, output_resource_format); |
221 if (resource_id == 0) { | 236 if (resource_id == 0) { |
222 allocation_success = false; | 237 allocation_success = false; |
223 break; | 238 break; |
224 } | 239 } |
| 240 all_resources_.push_back(resource_id); |
| 241 |
| 242 gpu::Mailbox mailbox; |
| 243 if (!software_compositor) { |
| 244 DCHECK(context_provider_); |
| 245 |
| 246 gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL(); |
| 247 |
| 248 GLC(gl, gl->GenMailboxCHROMIUM(mailbox.name)); |
| 249 ResourceProvider::ScopedWriteLockGL lock(resource_provider_, resource_id); |
| 250 GLC(gl, gl->ProduceTextureDirectCHROMIUM(lock.texture_id(), GL_TEXTURE_2D, |
| 251 mailbox.name)); |
| 252 } |
225 | 253 |
226 DCHECK(software_compositor || !mailbox.IsZero()); | 254 DCHECK(software_compositor || !mailbox.IsZero()); |
227 plane_resources.push_back(PlaneResource(resource_id, | 255 plane_resources.push_back(PlaneResource(resource_id, |
228 output_plane_resource_size, | 256 output_plane_resource_size, |
229 output_resource_format, | 257 output_resource_format, |
230 mailbox)); | 258 mailbox)); |
231 } | 259 } |
232 | 260 |
233 if (!allocation_success) { | 261 if (!allocation_success) { |
234 for (size_t i = 0; i < plane_resources.size(); ++i) | 262 for (size_t i = 0; i < plane_resources.size(); ++i) |
235 DeleteResource(plane_resources[i].resource_id); | 263 DeleteResource(plane_resources[i].resource_id); |
236 return VideoFrameExternalResources(); | 264 return VideoFrameExternalResources(); |
237 } | 265 } |
238 | 266 |
239 VideoFrameExternalResources external_resources; | 267 VideoFrameExternalResources external_resources; |
240 | 268 |
241 if (software_compositor) { | 269 if (software_compositor) { |
242 DCHECK_EQ(plane_resources.size(), 1u); | 270 DCHECK_EQ(plane_resources.size(), 1u); |
243 DCHECK_EQ(plane_resources[0].resource_format, kRGBResourceFormat); | 271 DCHECK_EQ(plane_resources[0].resource_format, kRGBResourceFormat); |
244 DCHECK(plane_resources[0].mailbox.IsZero()); | 272 DCHECK(plane_resources[0].mailbox.IsZero()); |
245 | 273 |
246 if (!video_renderer_) | 274 if (!PlaneResourceMatchesUniqueID(plane_resources[0], video_frame.get(), |
247 video_renderer_.reset(new media::SkCanvasVideoRenderer); | 275 0)) { |
| 276 // We need to transfer data from |video_frame| to the plane resource. |
| 277 if (!video_renderer_) |
| 278 video_renderer_.reset(new media::SkCanvasVideoRenderer); |
248 | 279 |
249 { | |
250 ResourceProvider::ScopedWriteLockSoftware lock( | 280 ResourceProvider::ScopedWriteLockSoftware lock( |
251 resource_provider_, plane_resources[0].resource_id); | 281 resource_provider_, plane_resources[0].resource_id); |
252 SkCanvas canvas(lock.sk_bitmap()); | 282 SkCanvas canvas(lock.sk_bitmap()); |
253 video_renderer_->Copy(video_frame, &canvas); | 283 video_renderer_->Copy(video_frame, &canvas); |
| 284 SetPlaneResourceUniqueId(video_frame.get(), 0, &plane_resources[0]); |
254 } | 285 } |
255 | 286 |
256 RecycleResourceData recycle_data = { | |
257 plane_resources[0].resource_id, | |
258 plane_resources[0].resource_size, | |
259 plane_resources[0].resource_format, | |
260 gpu::Mailbox() | |
261 }; | |
262 external_resources.software_resources.push_back( | 287 external_resources.software_resources.push_back( |
263 plane_resources[0].resource_id); | 288 plane_resources[0].resource_id); |
264 external_resources.software_release_callback = | 289 external_resources.software_release_callback = |
265 base::Bind(&RecycleResource, AsWeakPtr(), recycle_data); | 290 base::Bind(&RecycleResource, AsWeakPtr(), plane_resources[0]); |
266 external_resources.type = VideoFrameExternalResources::SOFTWARE_RESOURCE; | 291 external_resources.type = VideoFrameExternalResources::SOFTWARE_RESOURCE; |
267 | 292 |
268 return external_resources; | 293 return external_resources; |
269 } | 294 } |
270 | 295 |
271 for (size_t i = 0; i < plane_resources.size(); ++i) { | 296 for (size_t i = 0; i < plane_resources.size(); ++i) { |
272 // Update each plane's resource id with its content. | 297 // Update each plane's resource id with its content. |
273 DCHECK_EQ(plane_resources[i].resource_format, kYUVResourceFormat); | 298 DCHECK_EQ(plane_resources[i].resource_format, |
| 299 resource_provider_->yuv_resource_format()); |
274 | 300 |
275 const uint8_t* input_plane_pixels = video_frame->data(i); | 301 if (!PlaneResourceMatchesUniqueID(plane_resources[i], video_frame.get(), |
| 302 i)) { |
| 303 // We need to transfer data from |video_frame| to the plane resource. |
| 304 const uint8_t* input_plane_pixels = video_frame->data(i); |
276 | 305 |
277 gfx::Rect image_rect(0, | 306 gfx::Rect image_rect(0, 0, video_frame->stride(i), |
278 0, | 307 plane_resources[i].resource_size.height()); |
279 video_frame->stride(i), | 308 gfx::Rect source_rect(plane_resources[i].resource_size); |
280 plane_resources[i].resource_size.height()); | 309 resource_provider_->SetPixels(plane_resources[i].resource_id, |
281 gfx::Rect source_rect(plane_resources[i].resource_size); | 310 input_plane_pixels, image_rect, source_rect, |
282 resource_provider_->SetPixels(plane_resources[i].resource_id, | 311 gfx::Vector2d()); |
283 input_plane_pixels, | 312 SetPlaneResourceUniqueId(video_frame.get(), i, &plane_resources[i]); |
284 image_rect, | 313 } |
285 source_rect, | |
286 gfx::Vector2d()); | |
287 | |
288 RecycleResourceData recycle_data = { | |
289 plane_resources[i].resource_id, | |
290 plane_resources[i].resource_size, | |
291 plane_resources[i].resource_format, | |
292 plane_resources[i].mailbox | |
293 }; | |
294 | 314 |
295 external_resources.mailboxes.push_back( | 315 external_resources.mailboxes.push_back( |
296 TextureMailbox(plane_resources[i].mailbox, GL_TEXTURE_2D, 0)); | 316 TextureMailbox(plane_resources[i].mailbox, GL_TEXTURE_2D, 0)); |
297 external_resources.release_callbacks.push_back( | 317 external_resources.release_callbacks.push_back( |
298 base::Bind(&RecycleResource, AsWeakPtr(), recycle_data)); | 318 base::Bind(&RecycleResource, AsWeakPtr(), plane_resources[i])); |
299 } | 319 } |
300 | 320 |
301 external_resources.type = VideoFrameExternalResources::YUV_RESOURCE; | 321 external_resources.type = VideoFrameExternalResources::YUV_RESOURCE; |
302 return external_resources; | 322 return external_resources; |
303 } | 323 } |
304 | 324 |
305 // static | 325 // static |
306 void VideoResourceUpdater::ReturnTexture( | 326 void VideoResourceUpdater::ReturnTexture( |
307 base::WeakPtr<VideoResourceUpdater> updater, | 327 base::WeakPtr<VideoResourceUpdater> updater, |
308 const scoped_refptr<media::VideoFrame>& video_frame, | 328 const scoped_refptr<media::VideoFrame>& video_frame, |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
355 mailbox_holder->texture_target, | 375 mailbox_holder->texture_target, |
356 mailbox_holder->sync_point)); | 376 mailbox_holder->sync_point)); |
357 external_resources.release_callbacks.push_back( | 377 external_resources.release_callbacks.push_back( |
358 base::Bind(&ReturnTexture, AsWeakPtr(), video_frame)); | 378 base::Bind(&ReturnTexture, AsWeakPtr(), video_frame)); |
359 return external_resources; | 379 return external_resources; |
360 } | 380 } |
361 | 381 |
362 // static | 382 // static |
363 void VideoResourceUpdater::RecycleResource( | 383 void VideoResourceUpdater::RecycleResource( |
364 base::WeakPtr<VideoResourceUpdater> updater, | 384 base::WeakPtr<VideoResourceUpdater> updater, |
365 RecycleResourceData data, | 385 PlaneResource data, |
366 uint32 sync_point, | 386 uint32 sync_point, |
367 bool lost_resource, | 387 bool lost_resource, |
368 BlockingTaskRunner* main_thread_task_runner) { | 388 BlockingTaskRunner* main_thread_task_runner) { |
369 if (!updater.get()) { | 389 if (!updater.get()) { |
370 // Resource was already deleted. | 390 // Resource was already deleted. |
371 return; | 391 return; |
372 } | 392 } |
373 | 393 |
374 ContextProvider* context_provider = updater->context_provider_; | 394 ContextProvider* context_provider = updater->context_provider_; |
375 if (context_provider && sync_point) { | 395 if (context_provider && sync_point) { |
376 GLC(context_provider->ContextGL(), | 396 GLC(context_provider->ContextGL(), |
377 context_provider->ContextGL()->WaitSyncPointCHROMIUM(sync_point)); | 397 context_provider->ContextGL()->WaitSyncPointCHROMIUM(sync_point)); |
378 } | 398 } |
379 | 399 |
380 if (lost_resource) { | 400 if (lost_resource) { |
381 updater->DeleteResource(data.resource_id); | 401 updater->DeleteResource(data.resource_id); |
382 return; | 402 return; |
383 } | 403 } |
384 | 404 |
385 // Drop recycled resources that are the wrong format. | 405 // Drop recycled resources that are the wrong format. |
386 while (!updater->recycled_resources_.empty() && | 406 while (!updater->recycled_resources_.empty() && |
387 updater->recycled_resources_.back().resource_format != | 407 updater->recycled_resources_.back().resource_format != |
388 data.resource_format) { | 408 data.resource_format) { |
389 updater->DeleteResource(updater->recycled_resources_.back().resource_id); | 409 updater->DeleteResource(updater->recycled_resources_.back().resource_id); |
390 updater->recycled_resources_.pop_back(); | 410 updater->recycled_resources_.pop_back(); |
391 } | 411 } |
392 | 412 |
393 PlaneResource recycled_resource(data.resource_id, | 413 updater->recycled_resources_.push_back(data); |
394 data.resource_size, | |
395 data.resource_format, | |
396 data.mailbox); | |
397 updater->recycled_resources_.push_back(recycled_resource); | |
398 } | 414 } |
399 | 415 |
400 } // namespace cc | 416 } // namespace cc |
OLD | NEW |