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 <stddef.h> | 7 #include <stddef.h> |
8 #include <stdint.h> | 8 #include <stdint.h> |
9 | 9 |
10 #include <algorithm> | 10 #include <algorithm> |
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
166 : context_provider_(context_provider), | 166 : context_provider_(context_provider), |
167 resource_provider_(resource_provider) { | 167 resource_provider_(resource_provider) { |
168 } | 168 } |
169 | 169 |
170 VideoResourceUpdater::~VideoResourceUpdater() { | 170 VideoResourceUpdater::~VideoResourceUpdater() { |
171 for (const PlaneResource& plane_resource : all_resources_) | 171 for (const PlaneResource& plane_resource : all_resources_) |
172 resource_provider_->DeleteResource(plane_resource.resource_id()); | 172 resource_provider_->DeleteResource(plane_resource.resource_id()); |
173 } | 173 } |
174 | 174 |
175 VideoResourceUpdater::ResourceList::iterator | 175 VideoResourceUpdater::ResourceList::iterator |
| 176 VideoResourceUpdater::RecycleOrAllocateResource( |
| 177 const gfx::Size& resource_size, |
| 178 ResourceFormat resource_format, |
| 179 const gfx::ColorSpace& color_space, |
| 180 bool software_resource, |
| 181 bool immutable_hint, |
| 182 int unique_id, |
| 183 int plane_index) { |
| 184 ResourceList::iterator recyclable_resource = all_resources_.end(); |
| 185 for (auto it = all_resources_.begin(); it != all_resources_.end(); ++it) { |
| 186 // If the plane index is valid (positive, or 0, meaning all planes) |
| 187 // then we are allowed to return a referenced resource that already |
| 188 // contains the right frame data. It's safe to reuse it even if |
| 189 // resource_provider_ holds some references to it, because those |
| 190 // references are read-only. |
| 191 if (plane_index != -1 && it->Matches(unique_id, plane_index)) { |
| 192 DCHECK(it->resource_size() == resource_size); |
| 193 DCHECK(it->resource_format() == resource_format); |
| 194 DCHECK(it->mailbox().IsZero() == software_resource); |
| 195 return it; |
| 196 } |
| 197 |
| 198 // Otherwise check whether this is an unreferenced resource of the right |
| 199 // format that we can recycle. Remember it, but don't return immediately, |
| 200 // because we still want to find any reusable resources. |
| 201 // Resources backed by SharedMemory are not ref-counted, unlike mailboxes, |
| 202 // so the definition of |in_use| must take this into account. Full |
| 203 // discussion in codereview.chromium.org/145273021. |
| 204 const bool in_use = |
| 205 it->has_refs() || |
| 206 (software_resource && |
| 207 resource_provider_->InUseByConsumer(it->resource_id())); |
| 208 |
| 209 if (!in_use && it->resource_size() == resource_size && |
| 210 it->resource_format() == resource_format && |
| 211 it->mailbox().IsZero() == software_resource && |
| 212 resource_provider_->IsImmutable(it->resource_id()) == immutable_hint) { |
| 213 recyclable_resource = it; |
| 214 } |
| 215 } |
| 216 |
| 217 if (recyclable_resource != all_resources_.end()) |
| 218 return recyclable_resource; |
| 219 |
| 220 // There was nothing available to reuse or recycle. Allocate a new resource. |
| 221 return AllocateResource(resource_size, resource_format, color_space, |
| 222 !software_resource, immutable_hint); |
| 223 } |
| 224 |
| 225 VideoResourceUpdater::ResourceList::iterator |
176 VideoResourceUpdater::AllocateResource(const gfx::Size& plane_size, | 226 VideoResourceUpdater::AllocateResource(const gfx::Size& plane_size, |
177 ResourceFormat format, | 227 ResourceFormat format, |
178 const gfx::ColorSpace& color_space, | 228 const gfx::ColorSpace& color_space, |
179 bool has_mailbox, | 229 bool has_mailbox, |
180 bool immutable_hint) { | 230 bool immutable_hint) { |
181 // TODO(danakj): Abstract out hw/sw resource create/delete from | 231 // TODO(danakj): Abstract out hw/sw resource create/delete from |
182 // ResourceProvider and stop using ResourceProvider in this class. | 232 // ResourceProvider and stop using ResourceProvider in this class. |
183 const ResourceId resource_id = resource_provider_->CreateResource( | 233 const ResourceId resource_id = resource_provider_->CreateResource( |
184 plane_size, immutable_hint ? ResourceProvider::TEXTURE_HINT_IMMUTABLE | 234 plane_size, immutable_hint ? ResourceProvider::TEXTURE_HINT_IMMUTABLE |
185 : ResourceProvider::TEXTURE_HINT_DEFAULT, | 235 : ResourceProvider::TEXTURE_HINT_DEFAULT, |
186 format, color_space); | 236 format, color_space); |
187 if (resource_id == 0) | 237 DCHECK_NE(resource_id, 0u); |
188 return all_resources_.end(); | |
189 | 238 |
190 gpu::Mailbox mailbox; | 239 gpu::Mailbox mailbox; |
191 if (has_mailbox) { | 240 if (has_mailbox) { |
192 DCHECK(context_provider_); | 241 DCHECK(context_provider_); |
193 | 242 |
194 gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL(); | 243 gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL(); |
195 | 244 |
196 gl->GenMailboxCHROMIUM(mailbox.name); | 245 gl->GenMailboxCHROMIUM(mailbox.name); |
197 ResourceProvider::ScopedWriteLockGL lock(resource_provider_, resource_id, | 246 ResourceProvider::ScopedWriteLockGL lock(resource_provider_, resource_id, |
198 false); | 247 false); |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
291 if (!media::IsYuvPlanar(input_frame_format)) { | 340 if (!media::IsYuvPlanar(input_frame_format)) { |
292 NOTREACHED() << media::VideoPixelFormatToString(input_frame_format); | 341 NOTREACHED() << media::VideoPixelFormatToString(input_frame_format); |
293 return VideoFrameExternalResources(); | 342 return VideoFrameExternalResources(); |
294 } | 343 } |
295 | 344 |
296 const bool software_compositor = context_provider_ == NULL; | 345 const bool software_compositor = context_provider_ == NULL; |
297 | 346 |
298 ResourceFormat output_resource_format = | 347 ResourceFormat output_resource_format = |
299 resource_provider_->YuvResourceFormat(bits_per_channel); | 348 resource_provider_->YuvResourceFormat(bits_per_channel); |
300 | 349 |
| 350 // If GPU compositing is enabled, but the output resource format |
| 351 // returned by the resource provider is RGBA_8888, then a GPU driver |
| 352 // bug workaround requires that YUV frames must be converted to RGB |
| 353 // before texture upload. |
| 354 bool texture_needs_rgb_conversion = |
| 355 !software_compositor && |
| 356 output_resource_format == ResourceFormat::RGBA_8888; |
301 size_t output_plane_count = media::VideoFrame::NumPlanes(input_frame_format); | 357 size_t output_plane_count = media::VideoFrame::NumPlanes(input_frame_format); |
302 | 358 |
303 // TODO(skaslev): If we're in software compositing mode, we do the YUV -> RGB | 359 // TODO(skaslev): If we're in software compositing mode, we do the YUV -> RGB |
304 // conversion here. That involves an extra copy of each frame to a bitmap. | 360 // conversion here. That involves an extra copy of each frame to a bitmap. |
305 // Obviously, this is suboptimal and should be addressed once ubercompositor | 361 // Obviously, this is suboptimal and should be addressed once ubercompositor |
306 // starts shaping up. | 362 // starts shaping up. |
307 if (software_compositor) { | 363 if (software_compositor || texture_needs_rgb_conversion) { |
308 output_resource_format = kRGBResourceFormat; | 364 output_resource_format = kRGBResourceFormat; |
309 output_plane_count = 1; | 365 output_plane_count = 1; |
| 366 bits_per_channel = 8; |
310 } | 367 } |
311 | 368 |
312 // Drop recycled resources that are the wrong format. | 369 // Drop recycled resources that are the wrong format. |
313 for (auto it = all_resources_.begin(); it != all_resources_.end();) { | 370 for (auto it = all_resources_.begin(); it != all_resources_.end();) { |
314 if (!it->has_refs() && it->resource_format() != output_resource_format) | 371 if (!it->has_refs() && it->resource_format() != output_resource_format) |
315 DeleteResource(it++); | 372 DeleteResource(it++); |
316 else | 373 else |
317 ++it; | 374 ++it; |
318 } | 375 } |
319 | 376 |
320 const int max_resource_size = resource_provider_->max_texture_size(); | 377 const int max_resource_size = resource_provider_->max_texture_size(); |
321 std::vector<ResourceList::iterator> plane_resources; | 378 std::vector<ResourceList::iterator> plane_resources; |
322 for (size_t i = 0; i < output_plane_count; ++i) { | 379 for (size_t i = 0; i < output_plane_count; ++i) { |
323 gfx::Size output_plane_resource_size = | 380 gfx::Size output_plane_resource_size = |
324 SoftwarePlaneDimension(video_frame.get(), software_compositor, i); | 381 SoftwarePlaneDimension(video_frame.get(), software_compositor, i); |
325 if (output_plane_resource_size.IsEmpty() || | 382 if (output_plane_resource_size.IsEmpty() || |
326 output_plane_resource_size.width() > max_resource_size || | 383 output_plane_resource_size.width() > max_resource_size || |
327 output_plane_resource_size.height() > max_resource_size) { | 384 output_plane_resource_size.height() > max_resource_size) { |
328 break; | 385 break; |
329 } | 386 } |
330 | 387 |
331 // Try recycle a previously-allocated resource. | 388 const bool is_immutable = true; |
332 ResourceList::iterator resource_it = all_resources_.end(); | 389 ResourceList::iterator resource_it = RecycleOrAllocateResource( |
333 for (auto it = all_resources_.begin(); it != all_resources_.end(); ++it) { | 390 output_plane_resource_size, output_resource_format, |
334 if (it->resource_size() == output_plane_resource_size && | 391 video_frame->ColorSpace(), software_compositor, is_immutable, |
335 it->resource_format() == output_resource_format) { | 392 video_frame->unique_id(), i); |
336 if (it->Matches(video_frame->unique_id(), i)) { | |
337 // Bingo, we found a resource that already contains the data we are | |
338 // planning to put in it. It's safe to reuse it even if | |
339 // resource_provider_ holds some references to it, because those | |
340 // references are read-only. | |
341 resource_it = it; | |
342 break; | |
343 } | |
344 | |
345 // This extra check is needed because resources backed by SharedMemory | |
346 // are not ref-counted, unlike mailboxes. Full discussion in | |
347 // codereview.chromium.org/145273021. | |
348 const bool in_use = | |
349 software_compositor && | |
350 resource_provider_->InUseByConsumer(it->resource_id()); | |
351 if (!it->has_refs() && !in_use) { | |
352 // We found a resource with the correct size that we can overwrite. | |
353 resource_it = it; | |
354 } | |
355 } | |
356 } | |
357 | |
358 // Check if we need to allocate a new resource. | |
359 if (resource_it == all_resources_.end()) { | |
360 const bool is_immutable = true; | |
361 resource_it = AllocateResource( | |
362 output_plane_resource_size, output_resource_format, | |
363 video_frame->ColorSpace(), !software_compositor, is_immutable); | |
364 } | |
365 if (resource_it == all_resources_.end()) | |
366 break; | |
367 | 393 |
368 resource_it->add_ref(); | 394 resource_it->add_ref(); |
369 plane_resources.push_back(resource_it); | 395 plane_resources.push_back(resource_it); |
370 } | 396 } |
371 | 397 |
372 if (plane_resources.size() != output_plane_count) { | |
373 // Allocation failed, nothing will be returned so restore reference counts. | |
374 for (ResourceList::iterator resource_it : plane_resources) | |
375 resource_it->remove_ref(); | |
376 return VideoFrameExternalResources(); | |
377 } | |
378 | |
379 VideoFrameExternalResources external_resources; | 398 VideoFrameExternalResources external_resources; |
380 | 399 |
381 external_resources.bits_per_channel = bits_per_channel; | 400 external_resources.bits_per_channel = bits_per_channel; |
382 | 401 |
383 if (software_compositor) { | 402 if (software_compositor || texture_needs_rgb_conversion) { |
384 DCHECK_EQ(plane_resources.size(), 1u); | 403 DCHECK_EQ(plane_resources.size(), 1u); |
385 PlaneResource& plane_resource = *plane_resources[0]; | 404 PlaneResource& plane_resource = *plane_resources[0]; |
386 DCHECK_EQ(plane_resource.resource_format(), kRGBResourceFormat); | 405 DCHECK_EQ(plane_resource.resource_format(), kRGBResourceFormat); |
387 DCHECK(plane_resource.mailbox().IsZero()); | 406 DCHECK_EQ(software_compositor, plane_resource.mailbox().IsZero()); |
388 | 407 |
389 if (!plane_resource.Matches(video_frame->unique_id(), 0)) { | 408 if (!plane_resource.Matches(video_frame->unique_id(), 0)) { |
390 // We need to transfer data from |video_frame| to the plane resource. | 409 // We need to transfer data from |video_frame| to the plane resource. |
391 if (!video_renderer_) | 410 if (software_compositor) { |
392 video_renderer_.reset(new media::SkCanvasVideoRenderer); | 411 if (!video_renderer_) |
| 412 video_renderer_.reset(new media::SkCanvasVideoRenderer); |
393 | 413 |
394 ResourceProvider::ScopedWriteLockSoftware lock( | 414 ResourceProvider::ScopedWriteLockSoftware lock( |
395 resource_provider_, plane_resource.resource_id()); | 415 resource_provider_, plane_resource.resource_id()); |
396 SkCanvas canvas(lock.sk_bitmap()); | 416 SkCanvas canvas(lock.sk_bitmap()); |
397 // This is software path, so canvas and video_frame are always backed | 417 // This is software path, so canvas and video_frame are always backed |
398 // by software. | 418 // by software. |
399 video_renderer_->Copy(video_frame, &canvas, media::Context3D()); | 419 video_renderer_->Copy(video_frame, &canvas, media::Context3D()); |
| 420 } else { |
| 421 size_t bytes_per_row = ResourceUtil::CheckedWidthInBytes<size_t>( |
| 422 video_frame->coded_size().width(), ResourceFormat::RGBA_8888); |
| 423 size_t needed_size = bytes_per_row * video_frame->coded_size().height(); |
| 424 if (upload_pixels_.size() < needed_size) |
| 425 upload_pixels_.resize(needed_size); |
| 426 |
| 427 media::SkCanvasVideoRenderer::ConvertVideoFrameToRGBPixels( |
| 428 video_frame.get(), &upload_pixels_[0], bytes_per_row); |
| 429 |
| 430 resource_provider_->CopyToResource(plane_resource.resource_id(), |
| 431 &upload_pixels_[0], |
| 432 plane_resource.resource_size()); |
| 433 } |
400 plane_resource.SetUniqueId(video_frame->unique_id(), 0); | 434 plane_resource.SetUniqueId(video_frame->unique_id(), 0); |
401 } | 435 } |
402 | 436 |
403 external_resources.software_resources.push_back( | 437 if (software_compositor) { |
404 plane_resource.resource_id()); | 438 external_resources.software_resources.push_back( |
405 external_resources.software_release_callback = | 439 plane_resource.resource_id()); |
406 base::Bind(&RecycleResource, AsWeakPtr(), plane_resource.resource_id()); | 440 external_resources.software_release_callback = base::Bind( |
407 external_resources.type = VideoFrameExternalResources::SOFTWARE_RESOURCE; | 441 &RecycleResource, AsWeakPtr(), plane_resource.resource_id()); |
| 442 external_resources.type = VideoFrameExternalResources::SOFTWARE_RESOURCE; |
| 443 } else { |
| 444 // VideoResourceUpdater shares a context with the compositor so |
| 445 // a sync token is not required. |
| 446 TextureMailbox mailbox(plane_resource.mailbox(), gpu::SyncToken(), |
| 447 resource_provider_->GetResourceTextureTarget( |
| 448 plane_resource.resource_id())); |
| 449 mailbox.set_color_space(video_frame->ColorSpace()); |
| 450 external_resources.mailboxes.push_back(mailbox); |
| 451 external_resources.release_callbacks.push_back(base::Bind( |
| 452 &RecycleResource, AsWeakPtr(), plane_resource.resource_id())); |
| 453 external_resources.type = VideoFrameExternalResources::RGBA_RESOURCE; |
| 454 } |
408 return external_resources; | 455 return external_resources; |
409 } | 456 } |
410 | 457 |
411 for (size_t i = 0; i < plane_resources.size(); ++i) { | 458 for (size_t i = 0; i < plane_resources.size(); ++i) { |
412 PlaneResource& plane_resource = *plane_resources[i]; | 459 PlaneResource& plane_resource = *plane_resources[i]; |
413 // Update each plane's resource id with its content. | 460 // Update each plane's resource id with its content. |
414 DCHECK_EQ(plane_resource.resource_format(), | 461 DCHECK_EQ(plane_resource.resource_format(), |
415 resource_provider_->YuvResourceFormat(bits_per_channel)); | 462 resource_provider_->YuvResourceFormat(bits_per_channel)); |
416 | 463 |
417 if (!plane_resource.Matches(video_frame->unique_id(), i)) { | 464 if (!plane_resource.Matches(video_frame->unique_id(), i)) { |
418 // We need to transfer data from |video_frame| to the plane resource. | 465 // We need to transfer data from |video_frame| to the plane resource. |
419 // TODO(reveman): Can use GpuMemoryBuffers here to improve performance. | 466 // TODO(reveman): Can use GpuMemoryBuffers here to improve performance. |
420 | 467 |
421 // The |resource_size_pixels| is the size of the resource we want to | 468 // The |resource_size_pixels| is the size of the resource we want to |
422 // upload to. | 469 // upload to. |
423 gfx::Size resource_size_pixels = plane_resource.resource_size(); | 470 gfx::Size resource_size_pixels = plane_resource.resource_size(); |
424 // The |video_stride_bytes| is the width of the video frame we are | 471 // The |video_stride_bytes| is the width of the video frame we are |
425 // uploading (including non-frame data to fill in the stride). | 472 // uploading (including non-frame data to fill in the stride). |
426 int video_stride_bytes = video_frame->stride(i); | 473 int video_stride_bytes = video_frame->stride(i); |
427 | 474 |
428 size_t bytes_per_row = ResourceUtil::UncheckedWidthInBytes<size_t>( | 475 size_t bytes_per_row = ResourceUtil::CheckedWidthInBytes<size_t>( |
429 resource_size_pixels.width(), plane_resource.resource_format()); | 476 resource_size_pixels.width(), plane_resource.resource_format()); |
430 // Use 4-byte row alignment (OpenGL default) for upload performance. | 477 // Use 4-byte row alignment (OpenGL default) for upload performance. |
431 // Assuming that GL_UNPACK_ALIGNMENT has not changed from default. | 478 // Assuming that GL_UNPACK_ALIGNMENT has not changed from default. |
432 size_t upload_image_stride = | 479 size_t upload_image_stride = |
433 MathUtil::UncheckedRoundUp<size_t>(bytes_per_row, 4u); | 480 MathUtil::CheckedRoundUp<size_t>(bytes_per_row, 4u); |
434 | 481 |
435 bool needs_conversion = false; | 482 bool needs_conversion = false; |
436 int shift = 0; | 483 int shift = 0; |
437 | 484 |
438 // LUMINANCE_F16 uses half-floats, so we always need a conversion step. | 485 // LUMINANCE_F16 uses half-floats, so we always need a conversion step. |
439 if (plane_resource.resource_format() == LUMINANCE_F16) { | 486 if (plane_resource.resource_format() == LUMINANCE_F16) { |
440 needs_conversion = true; | 487 needs_conversion = true; |
441 // Note that the current method of converting integers to half-floats | 488 // Note that the current method of converting integers to half-floats |
442 // stops working if you have more than 10 bits of data. | 489 // stops working if you have more than 10 bits of data. |
443 DCHECK_LE(bits_per_channel, 10); | 490 DCHECK_LE(bits_per_channel, 10); |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
512 // | 559 // |
513 // PLEASE NOTE: This doesn't work if bits_per_channel is > 10. | 560 // PLEASE NOTE: This doesn't work if bits_per_channel is > 10. |
514 // PLEASE NOTE: All planes are assumed to use the same multiplier/offset. | 561 // PLEASE NOTE: All planes are assumed to use the same multiplier/offset. |
515 external_resources.offset = 0.5f; | 562 external_resources.offset = 0.5f; |
516 // Max value from input data. | 563 // Max value from input data. |
517 int max_input_value = (1 << bits_per_channel) - 1; | 564 int max_input_value = (1 << bits_per_channel) - 1; |
518 // 2 << 11 = 2048 would be 1.0 with our exponent. | 565 // 2 << 11 = 2048 would be 1.0 with our exponent. |
519 external_resources.multiplier = 2048.0 / max_input_value; | 566 external_resources.multiplier = 2048.0 / max_input_value; |
520 } | 567 } |
521 | 568 |
| 569 // VideoResourceUpdater shares a context with the compositor so a |
| 570 // sync token is not required. |
522 TextureMailbox mailbox(plane_resource.mailbox(), gpu::SyncToken(), | 571 TextureMailbox mailbox(plane_resource.mailbox(), gpu::SyncToken(), |
523 resource_provider_->GetResourceTextureTarget( | 572 resource_provider_->GetResourceTextureTarget( |
524 plane_resource.resource_id())); | 573 plane_resource.resource_id())); |
525 mailbox.set_color_space(video_frame->ColorSpace()); | 574 mailbox.set_color_space(video_frame->ColorSpace()); |
526 external_resources.mailboxes.push_back(mailbox); | 575 external_resources.mailboxes.push_back(mailbox); |
527 external_resources.release_callbacks.push_back(base::Bind( | 576 external_resources.release_callbacks.push_back(base::Bind( |
528 &RecycleResource, AsWeakPtr(), plane_resource.resource_id())); | 577 &RecycleResource, AsWeakPtr(), plane_resource.resource_id())); |
529 } | 578 } |
530 | 579 |
531 external_resources.type = VideoFrameExternalResources::YUV_RESOURCE; | 580 external_resources.type = VideoFrameExternalResources::YUV_RESOURCE; |
(...skipping 26 matching lines...) Expand all Loading... |
558 const gpu::MailboxHolder& mailbox_holder, | 607 const gpu::MailboxHolder& mailbox_holder, |
559 VideoFrameExternalResources* external_resources) { | 608 VideoFrameExternalResources* external_resources) { |
560 gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL(); | 609 gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL(); |
561 SyncTokenClientImpl client(gl, mailbox_holder.sync_token); | 610 SyncTokenClientImpl client(gl, mailbox_holder.sync_token); |
562 | 611 |
563 const gfx::Size output_plane_resource_size = video_frame->coded_size(); | 612 const gfx::Size output_plane_resource_size = video_frame->coded_size(); |
564 // The copy needs to be a direct transfer of pixel data, so we use an RGBA8 | 613 // The copy needs to be a direct transfer of pixel data, so we use an RGBA8 |
565 // target to avoid loss of precision or dropping any alpha component. | 614 // target to avoid loss of precision or dropping any alpha component. |
566 const ResourceFormat copy_target_format = ResourceFormat::RGBA_8888; | 615 const ResourceFormat copy_target_format = ResourceFormat::RGBA_8888; |
567 | 616 |
568 // Search for an existing resource to reuse. | 617 const bool is_immutable = false; |
569 VideoResourceUpdater::ResourceList::iterator resource = all_resources_.end(); | 618 const int no_unique_id = 0; |
570 | 619 const int no_plane_index = -1; // Do not recycle referenced textures. |
571 for (auto it = all_resources_.begin(); it != all_resources_.end(); ++it) { | 620 VideoResourceUpdater::ResourceList::iterator resource = |
572 // Reuse resource if attributes match and the resource is a currently | 621 RecycleOrAllocateResource(output_plane_resource_size, copy_target_format, |
573 // unreferenced texture. | 622 video_frame->ColorSpace(), false, is_immutable, |
574 if (it->resource_size() == output_plane_resource_size && | 623 no_unique_id, no_plane_index); |
575 it->resource_format() == copy_target_format && | |
576 !it->mailbox().IsZero() && !it->has_refs() && | |
577 resource_provider_->GetTextureHint(it->resource_id()) != | |
578 ResourceProvider::TEXTURE_HINT_IMMUTABLE) { | |
579 resource = it; | |
580 break; | |
581 } | |
582 } | |
583 | |
584 // Otherwise allocate a new resource. | |
585 if (resource == all_resources_.end()) { | |
586 const bool is_immutable = false; | |
587 resource = AllocateResource(output_plane_resource_size, copy_target_format, | |
588 video_frame->ColorSpace(), true, is_immutable); | |
589 } | |
590 | |
591 resource->add_ref(); | 624 resource->add_ref(); |
592 | 625 |
593 ResourceProvider::ScopedWriteLockGL lock(resource_provider_, | 626 ResourceProvider::ScopedWriteLockGL lock(resource_provider_, |
594 resource->resource_id(), false); | 627 resource->resource_id(), false); |
595 DCHECK_EQ( | 628 DCHECK_EQ( |
596 resource_provider_->GetResourceTextureTarget(resource->resource_id()), | 629 resource_provider_->GetResourceTextureTarget(resource->resource_id()), |
597 (GLenum)GL_TEXTURE_2D); | 630 (GLenum)GL_TEXTURE_2D); |
598 | 631 |
599 gl->WaitSyncTokenCHROMIUM(mailbox_holder.sync_token.GetConstData()); | 632 gl->WaitSyncTokenCHROMIUM(mailbox_holder.sync_token.GetConstData()); |
600 uint32_t src_texture_id = gl->CreateAndConsumeTextureCHROMIUM( | 633 uint32_t src_texture_id = gl->CreateAndConsumeTextureCHROMIUM( |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
672 void VideoResourceUpdater::RecycleResource( | 705 void VideoResourceUpdater::RecycleResource( |
673 base::WeakPtr<VideoResourceUpdater> updater, | 706 base::WeakPtr<VideoResourceUpdater> updater, |
674 ResourceId resource_id, | 707 ResourceId resource_id, |
675 const gpu::SyncToken& sync_token, | 708 const gpu::SyncToken& sync_token, |
676 bool lost_resource, | 709 bool lost_resource, |
677 BlockingTaskRunner* main_thread_task_runner) { | 710 BlockingTaskRunner* main_thread_task_runner) { |
678 if (!updater.get()) { | 711 if (!updater.get()) { |
679 // Resource was already deleted. | 712 // Resource was already deleted. |
680 return; | 713 return; |
681 } | 714 } |
682 | |
683 const ResourceList::iterator resource_it = std::find_if( | 715 const ResourceList::iterator resource_it = std::find_if( |
684 updater->all_resources_.begin(), updater->all_resources_.end(), | 716 updater->all_resources_.begin(), updater->all_resources_.end(), |
685 [resource_id](const PlaneResource& plane_resource) { | 717 [resource_id](const PlaneResource& plane_resource) { |
686 return plane_resource.resource_id() == resource_id; | 718 return plane_resource.resource_id() == resource_id; |
687 }); | 719 }); |
688 if (resource_it == updater->all_resources_.end()) | 720 if (resource_it == updater->all_resources_.end()) |
689 return; | 721 return; |
690 | 722 |
691 ContextProvider* context_provider = updater->context_provider_; | 723 ContextProvider* context_provider = updater->context_provider_; |
692 if (context_provider && sync_token.HasData()) { | 724 if (context_provider && sync_token.HasData()) { |
693 context_provider->ContextGL()->WaitSyncTokenCHROMIUM( | 725 context_provider->ContextGL()->WaitSyncTokenCHROMIUM( |
694 sync_token.GetConstData()); | 726 sync_token.GetConstData()); |
695 } | 727 } |
696 | 728 |
697 if (lost_resource) { | 729 if (lost_resource) { |
698 resource_it->clear_refs(); | 730 resource_it->clear_refs(); |
699 updater->DeleteResource(resource_it); | 731 updater->DeleteResource(resource_it); |
700 return; | 732 return; |
701 } | 733 } |
702 | 734 |
703 resource_it->remove_ref(); | 735 resource_it->remove_ref(); |
704 } | 736 } |
705 | 737 |
706 } // namespace cc | 738 } // namespace cc |
OLD | NEW |