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 <algorithm> |
| 8 |
7 #include "base/bind.h" | 9 #include "base/bind.h" |
8 #include "base/debug/trace_event.h" | 10 #include "base/debug/trace_event.h" |
9 #include "cc/output/gl_renderer.h" | 11 #include "cc/output/gl_renderer.h" |
10 #include "cc/resources/resource_provider.h" | 12 #include "cc/resources/resource_provider.h" |
11 #include "gpu/GLES2/gl2extchromium.h" | 13 #include "gpu/GLES2/gl2extchromium.h" |
12 #include "gpu/command_buffer/client/gles2_interface.h" | 14 #include "gpu/command_buffer/client/gles2_interface.h" |
13 #include "media/base/video_frame.h" | 15 #include "media/base/video_frame.h" |
14 #include "media/filters/skcanvas_video_renderer.h" | 16 #include "media/filters/skcanvas_video_renderer.h" |
15 #include "third_party/khronos/GLES2/gl2.h" | 17 #include "third_party/khronos/GLES2/gl2.h" |
16 #include "third_party/khronos/GLES2/gl2ext.h" | 18 #include "third_party/khronos/GLES2/gl2ext.h" |
(...skipping 24 matching lines...) Expand all Loading... |
41 | 43 |
42 VideoResourceUpdater::PlaneResource::PlaneResource( | 44 VideoResourceUpdater::PlaneResource::PlaneResource( |
43 unsigned int resource_id, | 45 unsigned int resource_id, |
44 const gfx::Size& resource_size, | 46 const gfx::Size& resource_size, |
45 ResourceFormat resource_format, | 47 ResourceFormat resource_format, |
46 gpu::Mailbox mailbox) | 48 gpu::Mailbox mailbox) |
47 : resource_id(resource_id), | 49 : resource_id(resource_id), |
48 resource_size(resource_size), | 50 resource_size(resource_size), |
49 resource_format(resource_format), | 51 resource_format(resource_format), |
50 mailbox(mailbox), | 52 mailbox(mailbox), |
| 53 ref_count(0), |
51 frame_ptr(nullptr), | 54 frame_ptr(nullptr), |
52 plane_index(0) { | 55 plane_index(0) { |
53 } | 56 } |
54 | 57 |
55 bool VideoResourceUpdater::PlaneResourceMatchesUniqueID( | 58 bool VideoResourceUpdater::PlaneResourceMatchesUniqueID( |
56 const PlaneResource& plane_resource, | 59 const PlaneResource& plane_resource, |
57 const media::VideoFrame* video_frame, | 60 const media::VideoFrame* video_frame, |
58 int plane_index) { | 61 int plane_index) { |
59 return plane_resource.frame_ptr == video_frame && | 62 return plane_resource.frame_ptr == video_frame && |
60 plane_resource.plane_index == plane_index && | 63 plane_resource.plane_index == plane_index && |
(...skipping 13 matching lines...) Expand all Loading... |
74 | 77 |
75 VideoFrameExternalResources::~VideoFrameExternalResources() {} | 78 VideoFrameExternalResources::~VideoFrameExternalResources() {} |
76 | 79 |
77 VideoResourceUpdater::VideoResourceUpdater(ContextProvider* context_provider, | 80 VideoResourceUpdater::VideoResourceUpdater(ContextProvider* context_provider, |
78 ResourceProvider* resource_provider) | 81 ResourceProvider* resource_provider) |
79 : context_provider_(context_provider), | 82 : context_provider_(context_provider), |
80 resource_provider_(resource_provider) { | 83 resource_provider_(resource_provider) { |
81 } | 84 } |
82 | 85 |
83 VideoResourceUpdater::~VideoResourceUpdater() { | 86 VideoResourceUpdater::~VideoResourceUpdater() { |
84 while (!all_resources_.empty()) { | 87 for (const PlaneResource& plane_resource : all_resources_) |
85 resource_provider_->DeleteResource(all_resources_.back()); | 88 resource_provider_->DeleteResource(plane_resource.resource_id); |
86 all_resources_.pop_back(); | |
87 } | |
88 } | 89 } |
89 | 90 |
90 void VideoResourceUpdater::DeleteResource(unsigned resource_id) { | 91 VideoResourceUpdater::ResourceList::iterator |
91 resource_provider_->DeleteResource(resource_id); | 92 VideoResourceUpdater::AllocateResource(const gfx::Size& plane_size, |
92 all_resources_.erase(std::remove(all_resources_.begin(), | 93 ResourceFormat format, |
93 all_resources_.end(), | 94 bool has_mailbox) { |
94 resource_id)); | 95 // TODO(danakj): Abstract out hw/sw resource create/delete from |
| 96 // ResourceProvider and stop using ResourceProvider in this class. |
| 97 const ResourceProvider::ResourceId resource_id = |
| 98 resource_provider_->CreateResource(plane_size, GL_CLAMP_TO_EDGE, |
| 99 ResourceProvider::TextureHintImmutable, |
| 100 format); |
| 101 if (resource_id == 0) |
| 102 return all_resources_.end(); |
| 103 |
| 104 gpu::Mailbox mailbox; |
| 105 if (has_mailbox) { |
| 106 DCHECK(context_provider_); |
| 107 |
| 108 gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL(); |
| 109 |
| 110 GLC(gl, gl->GenMailboxCHROMIUM(mailbox.name)); |
| 111 ResourceProvider::ScopedWriteLockGL lock(resource_provider_, resource_id); |
| 112 GLC(gl, gl->ProduceTextureDirectCHROMIUM(lock.texture_id(), GL_TEXTURE_2D, |
| 113 mailbox.name)); |
| 114 } |
| 115 all_resources_.push_front( |
| 116 PlaneResource(resource_id, plane_size, format, mailbox)); |
| 117 return all_resources_.begin(); |
| 118 } |
| 119 |
| 120 void VideoResourceUpdater::DeleteResource(ResourceList::iterator resource_it) { |
| 121 DCHECK_EQ(resource_it->ref_count, 0); |
| 122 resource_provider_->DeleteResource(resource_it->resource_id); |
| 123 all_resources_.erase(resource_it); |
95 } | 124 } |
96 | 125 |
97 VideoFrameExternalResources VideoResourceUpdater:: | 126 VideoFrameExternalResources VideoResourceUpdater:: |
98 CreateExternalResourcesFromVideoFrame( | 127 CreateExternalResourcesFromVideoFrame( |
99 const scoped_refptr<media::VideoFrame>& video_frame) { | 128 const scoped_refptr<media::VideoFrame>& video_frame) { |
100 if (!VerifyFrame(video_frame)) | 129 if (!VerifyFrame(video_frame)) |
101 return VideoFrameExternalResources(); | 130 return VideoFrameExternalResources(); |
102 | 131 |
103 if (video_frame->format() == media::VideoFrame::NATIVE_TEXTURE) | 132 if (video_frame->format() == media::VideoFrame::NATIVE_TEXTURE) |
104 return CreateForHardwarePlanes(video_frame); | 133 return CreateForHardwarePlanes(video_frame); |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
150 | 179 |
151 #if defined(VIDEO_HOLE) | 180 #if defined(VIDEO_HOLE) |
152 if (input_frame_format == media::VideoFrame::HOLE) { | 181 if (input_frame_format == media::VideoFrame::HOLE) { |
153 VideoFrameExternalResources external_resources; | 182 VideoFrameExternalResources external_resources; |
154 external_resources.type = VideoFrameExternalResources::HOLE; | 183 external_resources.type = VideoFrameExternalResources::HOLE; |
155 return external_resources; | 184 return external_resources; |
156 } | 185 } |
157 #endif // defined(VIDEO_HOLE) | 186 #endif // defined(VIDEO_HOLE) |
158 | 187 |
159 // Only YUV software video frames are supported. | 188 // Only YUV software video frames are supported. |
160 DCHECK(input_frame_format == media::VideoFrame::YV12 || | |
161 input_frame_format == media::VideoFrame::I420 || | |
162 input_frame_format == media::VideoFrame::YV12A || | |
163 input_frame_format == media::VideoFrame::YV12J || | |
164 input_frame_format == media::VideoFrame::YV16 || | |
165 input_frame_format == media::VideoFrame::YV24); | |
166 if (input_frame_format != media::VideoFrame::YV12 && | 189 if (input_frame_format != media::VideoFrame::YV12 && |
167 input_frame_format != media::VideoFrame::I420 && | 190 input_frame_format != media::VideoFrame::I420 && |
168 input_frame_format != media::VideoFrame::YV12A && | 191 input_frame_format != media::VideoFrame::YV12A && |
169 input_frame_format != media::VideoFrame::YV12J && | 192 input_frame_format != media::VideoFrame::YV12J && |
170 input_frame_format != media::VideoFrame::YV16 && | 193 input_frame_format != media::VideoFrame::YV16 && |
171 input_frame_format != media::VideoFrame::YV24) | 194 input_frame_format != media::VideoFrame::YV24) { |
| 195 NOTREACHED() << input_frame_format; |
172 return VideoFrameExternalResources(); | 196 return VideoFrameExternalResources(); |
| 197 } |
173 | 198 |
174 bool software_compositor = context_provider_ == NULL; | 199 bool software_compositor = context_provider_ == NULL; |
175 | 200 |
176 ResourceFormat output_resource_format = | 201 ResourceFormat output_resource_format = |
177 resource_provider_->yuv_resource_format(); | 202 resource_provider_->yuv_resource_format(); |
178 size_t output_plane_count = media::VideoFrame::NumPlanes(input_frame_format); | 203 size_t output_plane_count = media::VideoFrame::NumPlanes(input_frame_format); |
179 | 204 |
180 // TODO(skaslev): If we're in software compositing mode, we do the YUV -> RGB | 205 // TODO(skaslev): If we're in software compositing mode, we do the YUV -> RGB |
181 // conversion here. That involves an extra copy of each frame to a bitmap. | 206 // conversion here. That involves an extra copy of each frame to a bitmap. |
182 // Obviously, this is suboptimal and should be addressed once ubercompositor | 207 // Obviously, this is suboptimal and should be addressed once ubercompositor |
183 // starts shaping up. | 208 // starts shaping up. |
184 if (software_compositor) { | 209 if (software_compositor) { |
185 output_resource_format = kRGBResourceFormat; | 210 output_resource_format = kRGBResourceFormat; |
186 output_plane_count = 1; | 211 output_plane_count = 1; |
187 } | 212 } |
188 | 213 |
189 int max_resource_size = resource_provider_->max_texture_size(); | 214 // Drop recycled resources that are the wrong format. |
190 std::vector<PlaneResource> plane_resources; | 215 for (auto it = all_resources_.begin(); it != all_resources_.end();) { |
191 bool allocation_success = true; | 216 if (it->ref_count == 0 && it->resource_format != output_resource_format) |
| 217 DeleteResource(it++); |
| 218 else |
| 219 ++it; |
| 220 } |
192 | 221 |
| 222 const int max_resource_size = resource_provider_->max_texture_size(); |
| 223 std::vector<ResourceList::iterator> plane_resources; |
193 for (size_t i = 0; i < output_plane_count; ++i) { | 224 for (size_t i = 0; i < output_plane_count; ++i) { |
194 gfx::Size output_plane_resource_size = | 225 gfx::Size output_plane_resource_size = |
195 SoftwarePlaneDimension(video_frame, software_compositor, i); | 226 SoftwarePlaneDimension(video_frame, software_compositor, i); |
196 if (output_plane_resource_size.IsEmpty() || | 227 if (output_plane_resource_size.IsEmpty() || |
197 output_plane_resource_size.width() > max_resource_size || | 228 output_plane_resource_size.width() > max_resource_size || |
198 output_plane_resource_size.height() > max_resource_size) { | 229 output_plane_resource_size.height() > max_resource_size) { |
199 allocation_success = false; | |
200 break; | 230 break; |
201 } | 231 } |
202 | 232 |
203 // Try recycle a previously-allocated resource. | 233 // Try recycle a previously-allocated resource. |
204 auto recycled_it = recycled_resources_.end(); | 234 ResourceList::iterator resource_it = all_resources_.end(); |
205 for (auto it = recycled_resources_.begin(); it != recycled_resources_.end(); | 235 for (auto it = all_resources_.begin(); it != all_resources_.end(); ++it) { |
206 ++it) { | 236 if (it->resource_size == output_plane_resource_size && |
207 const bool resource_matches = | 237 it->resource_format == output_resource_format) { |
208 it->resource_format == output_resource_format && | 238 if (PlaneResourceMatchesUniqueID(*it, video_frame.get(), i)) { |
209 it->resource_size == output_plane_resource_size; | 239 // Bingo, we found a resource that already contains the data we are |
210 const bool in_use = software_compositor && | 240 // planning to put in it. It's safe to reuse it even if |
211 resource_provider_->InUseByConsumer(it->resource_id); | 241 // resource_provider_ holds some references to it, because those |
212 if (resource_matches && !in_use) { | 242 // references are read-only. |
213 // We found a recycled resource with the allocation size and format we | 243 resource_it = it; |
214 // are looking for. | |
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; | 244 break; |
| 245 } |
| 246 |
| 247 // This extra check is needed because resources backed by SharedMemory |
| 248 // are not ref-counted, unlike mailboxes. Full discussion in |
| 249 // codereview.chromium.org/145273021. |
| 250 const bool in_use = |
| 251 software_compositor && |
| 252 resource_provider_->InUseByConsumer(it->resource_id); |
| 253 if (it->ref_count == 0 && !in_use) { |
| 254 // We found a resource with the correct size that we can overwrite. |
| 255 resource_it = it; |
| 256 } |
220 } | 257 } |
221 } | 258 } |
222 | 259 |
223 // Check if we can avoid allocating a new resource. | 260 // Check if we need to allocate a new resource. |
224 if (recycled_it != recycled_resources_.end()) { | 261 if (resource_it == all_resources_.end()) { |
225 plane_resources.push_back(*recycled_it); | 262 resource_it = |
226 recycled_resources_.erase(recycled_it); | 263 AllocateResource(output_plane_resource_size, output_resource_format, |
227 continue; | 264 !software_compositor); |
228 } | 265 } |
| 266 if (resource_it == all_resources_.end()) |
| 267 break; |
229 | 268 |
230 // TODO(danakj): Abstract out hw/sw resource create/delete from | 269 ++resource_it->ref_count; |
231 // ResourceProvider and stop using ResourceProvider in this class. | 270 plane_resources.push_back(resource_it); |
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); | |
236 if (resource_id == 0) { | |
237 allocation_success = false; | |
238 break; | |
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 } | |
253 | |
254 DCHECK(software_compositor || !mailbox.IsZero()); | |
255 plane_resources.push_back(PlaneResource(resource_id, | |
256 output_plane_resource_size, | |
257 output_resource_format, | |
258 mailbox)); | |
259 } | 271 } |
260 | 272 |
261 if (!allocation_success) { | 273 if (plane_resources.size() != output_plane_count) { |
262 for (size_t i = 0; i < plane_resources.size(); ++i) | 274 // Allocation failed, nothing will be returned so restore reference counts. |
263 DeleteResource(plane_resources[i].resource_id); | 275 for (ResourceList::iterator resource_it : plane_resources) |
| 276 --resource_it->ref_count; |
264 return VideoFrameExternalResources(); | 277 return VideoFrameExternalResources(); |
265 } | 278 } |
266 | 279 |
267 VideoFrameExternalResources external_resources; | 280 VideoFrameExternalResources external_resources; |
268 | 281 |
269 if (software_compositor) { | 282 if (software_compositor) { |
270 DCHECK_EQ(plane_resources.size(), 1u); | 283 DCHECK_EQ(plane_resources.size(), 1u); |
271 DCHECK_EQ(plane_resources[0].resource_format, kRGBResourceFormat); | 284 PlaneResource& plane_resource = *plane_resources[0]; |
272 DCHECK(plane_resources[0].mailbox.IsZero()); | 285 DCHECK_EQ(plane_resource.resource_format, kRGBResourceFormat); |
| 286 DCHECK(plane_resource.mailbox.IsZero()); |
273 | 287 |
274 if (!PlaneResourceMatchesUniqueID(plane_resources[0], video_frame.get(), | 288 if (!PlaneResourceMatchesUniqueID(plane_resource, video_frame.get(), 0)) { |
275 0)) { | |
276 // We need to transfer data from |video_frame| to the plane resource. | 289 // We need to transfer data from |video_frame| to the plane resource. |
277 if (!video_renderer_) | 290 if (!video_renderer_) |
278 video_renderer_.reset(new media::SkCanvasVideoRenderer); | 291 video_renderer_.reset(new media::SkCanvasVideoRenderer); |
279 | 292 |
280 ResourceProvider::ScopedWriteLockSoftware lock( | 293 ResourceProvider::ScopedWriteLockSoftware lock( |
281 resource_provider_, plane_resources[0].resource_id); | 294 resource_provider_, plane_resource.resource_id); |
282 SkCanvas canvas(lock.sk_bitmap()); | 295 SkCanvas canvas(lock.sk_bitmap()); |
283 video_renderer_->Copy(video_frame, &canvas); | 296 video_renderer_->Copy(video_frame, &canvas); |
284 SetPlaneResourceUniqueId(video_frame.get(), 0, &plane_resources[0]); | 297 SetPlaneResourceUniqueId(video_frame.get(), 0, &plane_resource); |
285 } | 298 } |
286 | 299 |
287 external_resources.software_resources.push_back( | 300 external_resources.software_resources.push_back(plane_resource.resource_id); |
288 plane_resources[0].resource_id); | |
289 external_resources.software_release_callback = | 301 external_resources.software_release_callback = |
290 base::Bind(&RecycleResource, AsWeakPtr(), plane_resources[0]); | 302 base::Bind(&RecycleResource, AsWeakPtr(), plane_resource.resource_id); |
291 external_resources.type = VideoFrameExternalResources::SOFTWARE_RESOURCE; | 303 external_resources.type = VideoFrameExternalResources::SOFTWARE_RESOURCE; |
292 | |
293 return external_resources; | 304 return external_resources; |
294 } | 305 } |
295 | 306 |
296 for (size_t i = 0; i < plane_resources.size(); ++i) { | 307 for (size_t i = 0; i < plane_resources.size(); ++i) { |
| 308 PlaneResource& plane_resource = *plane_resources[i]; |
297 // Update each plane's resource id with its content. | 309 // Update each plane's resource id with its content. |
298 DCHECK_EQ(plane_resources[i].resource_format, | 310 DCHECK_EQ(plane_resource.resource_format, |
299 resource_provider_->yuv_resource_format()); | 311 resource_provider_->yuv_resource_format()); |
300 | 312 |
301 if (!PlaneResourceMatchesUniqueID(plane_resources[i], video_frame.get(), | 313 if (!PlaneResourceMatchesUniqueID(plane_resource, video_frame.get(), i)) { |
302 i)) { | |
303 // We need to transfer data from |video_frame| to the plane resource. | 314 // We need to transfer data from |video_frame| to the plane resource. |
304 const uint8_t* input_plane_pixels = video_frame->data(i); | 315 const uint8_t* input_plane_pixels = video_frame->data(i); |
305 | 316 |
306 gfx::Rect image_rect(0, 0, video_frame->stride(i), | 317 gfx::Rect image_rect(0, 0, video_frame->stride(i), |
307 plane_resources[i].resource_size.height()); | 318 plane_resource.resource_size.height()); |
308 gfx::Rect source_rect(plane_resources[i].resource_size); | 319 gfx::Rect source_rect(plane_resource.resource_size); |
309 resource_provider_->SetPixels(plane_resources[i].resource_id, | 320 resource_provider_->SetPixels(plane_resource.resource_id, |
310 input_plane_pixels, image_rect, source_rect, | 321 input_plane_pixels, image_rect, source_rect, |
311 gfx::Vector2d()); | 322 gfx::Vector2d()); |
312 SetPlaneResourceUniqueId(video_frame.get(), i, &plane_resources[i]); | 323 SetPlaneResourceUniqueId(video_frame.get(), i, &plane_resource); |
313 } | 324 } |
314 | 325 |
315 external_resources.mailboxes.push_back( | 326 external_resources.mailboxes.push_back( |
316 TextureMailbox(plane_resources[i].mailbox, GL_TEXTURE_2D, 0)); | 327 TextureMailbox(plane_resource.mailbox, GL_TEXTURE_2D, 0)); |
317 external_resources.release_callbacks.push_back( | 328 external_resources.release_callbacks.push_back( |
318 base::Bind(&RecycleResource, AsWeakPtr(), plane_resources[i])); | 329 base::Bind(&RecycleResource, AsWeakPtr(), plane_resource.resource_id)); |
319 } | 330 } |
320 | 331 |
321 external_resources.type = VideoFrameExternalResources::YUV_RESOURCE; | 332 external_resources.type = VideoFrameExternalResources::YUV_RESOURCE; |
322 return external_resources; | 333 return external_resources; |
323 } | 334 } |
324 | 335 |
325 // static | 336 // static |
326 void VideoResourceUpdater::ReturnTexture( | 337 void VideoResourceUpdater::ReturnTexture( |
327 base::WeakPtr<VideoResourceUpdater> updater, | 338 base::WeakPtr<VideoResourceUpdater> updater, |
328 const scoped_refptr<media::VideoFrame>& video_frame, | 339 const scoped_refptr<media::VideoFrame>& video_frame, |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
375 mailbox_holder->texture_target, | 386 mailbox_holder->texture_target, |
376 mailbox_holder->sync_point)); | 387 mailbox_holder->sync_point)); |
377 external_resources.release_callbacks.push_back( | 388 external_resources.release_callbacks.push_back( |
378 base::Bind(&ReturnTexture, AsWeakPtr(), video_frame)); | 389 base::Bind(&ReturnTexture, AsWeakPtr(), video_frame)); |
379 return external_resources; | 390 return external_resources; |
380 } | 391 } |
381 | 392 |
382 // static | 393 // static |
383 void VideoResourceUpdater::RecycleResource( | 394 void VideoResourceUpdater::RecycleResource( |
384 base::WeakPtr<VideoResourceUpdater> updater, | 395 base::WeakPtr<VideoResourceUpdater> updater, |
385 PlaneResource data, | 396 ResourceProvider::ResourceId resource_id, |
386 uint32 sync_point, | 397 uint32 sync_point, |
387 bool lost_resource, | 398 bool lost_resource, |
388 BlockingTaskRunner* main_thread_task_runner) { | 399 BlockingTaskRunner* main_thread_task_runner) { |
389 if (!updater.get()) { | 400 if (!updater.get()) { |
390 // Resource was already deleted. | 401 // Resource was already deleted. |
391 return; | 402 return; |
392 } | 403 } |
393 | 404 |
| 405 const ResourceList::iterator resource_it = std::find_if( |
| 406 updater->all_resources_.begin(), updater->all_resources_.end(), |
| 407 [resource_id](const PlaneResource& plane_resource) { |
| 408 return plane_resource.resource_id == resource_id; |
| 409 }); |
| 410 if (resource_it == updater->all_resources_.end()) |
| 411 return; |
| 412 |
394 ContextProvider* context_provider = updater->context_provider_; | 413 ContextProvider* context_provider = updater->context_provider_; |
395 if (context_provider && sync_point) { | 414 if (context_provider && sync_point) { |
396 GLC(context_provider->ContextGL(), | 415 GLC(context_provider->ContextGL(), |
397 context_provider->ContextGL()->WaitSyncPointCHROMIUM(sync_point)); | 416 context_provider->ContextGL()->WaitSyncPointCHROMIUM(sync_point)); |
398 } | 417 } |
399 | 418 |
400 if (lost_resource) { | 419 if (lost_resource) { |
401 updater->DeleteResource(data.resource_id); | 420 resource_it->ref_count = 0; |
| 421 updater->DeleteResource(resource_it); |
402 return; | 422 return; |
403 } | 423 } |
404 | 424 |
405 // Drop recycled resources that are the wrong format. | 425 --resource_it->ref_count; |
406 while (!updater->recycled_resources_.empty() && | 426 DCHECK_GE(resource_it->ref_count, 0); |
407 updater->recycled_resources_.back().resource_format != | |
408 data.resource_format) { | |
409 updater->DeleteResource(updater->recycled_resources_.back().resource_id); | |
410 updater->recycled_resources_.pop_back(); | |
411 } | |
412 | |
413 updater->recycled_resources_.push_back(data); | |
414 } | 427 } |
415 | 428 |
416 } // namespace cc | 429 } // namespace cc |
OLD | NEW |