| 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 428 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 439 ResourceFormat output_resource_format; | 439 ResourceFormat output_resource_format; |
| 440 if (input_frame_format == media::PIXEL_FORMAT_Y16) { | 440 if (input_frame_format == media::PIXEL_FORMAT_Y16) { |
| 441 // Unable to display directly as yuv planes so convert it to RGBA for | 441 // Unable to display directly as yuv planes so convert it to RGBA for |
| 442 // compositing. | 442 // compositing. |
| 443 output_resource_format = RGBA_8888; | 443 output_resource_format = RGBA_8888; |
| 444 } else { | 444 } else { |
| 445 // Can be composited directly from yuv planes. | 445 // Can be composited directly from yuv planes. |
| 446 output_resource_format = | 446 output_resource_format = |
| 447 resource_provider_->YuvResourceFormat(bits_per_channel); | 447 resource_provider_->YuvResourceFormat(bits_per_channel); |
| 448 } | 448 } |
| 449 gfx::ColorSpace output_color_space = video_frame->ColorSpace(); |
| 449 | 450 |
| 450 // If GPU compositing is enabled, but the output resource format | 451 // If GPU compositing is enabled, but the output resource format |
| 451 // returned by the resource provider is RGBA_8888, then a GPU driver | 452 // returned by the resource provider is RGBA_8888, then a GPU driver |
| 452 // bug workaround requires that YUV frames must be converted to RGB | 453 // bug workaround requires that YUV frames must be converted to RGB |
| 453 // before texture upload. | 454 // before texture upload. |
| 454 bool texture_needs_rgb_conversion = | 455 bool texture_needs_rgb_conversion = |
| 455 !software_compositor && | 456 !software_compositor && |
| 456 output_resource_format == ResourceFormat::RGBA_8888; | 457 output_resource_format == ResourceFormat::RGBA_8888; |
| 457 size_t output_plane_count = media::VideoFrame::NumPlanes(input_frame_format); | 458 size_t output_plane_count = media::VideoFrame::NumPlanes(input_frame_format); |
| 458 | 459 |
| 459 // TODO(skaslev): If we're in software compositing mode, we do the YUV -> RGB | 460 // TODO(skaslev): If we're in software compositing mode, we do the YUV -> RGB |
| 460 // conversion here. That involves an extra copy of each frame to a bitmap. | 461 // conversion here. That involves an extra copy of each frame to a bitmap. |
| 461 // Obviously, this is suboptimal and should be addressed once ubercompositor | 462 // Obviously, this is suboptimal and should be addressed once ubercompositor |
| 462 // starts shaping up. | 463 // starts shaping up. |
| 463 if (software_compositor || texture_needs_rgb_conversion) { | 464 if (software_compositor || texture_needs_rgb_conversion) { |
| 465 output_color_space = output_color_space.GetAsFullRangeRGB(); |
| 464 output_resource_format = kRGBResourceFormat; | 466 output_resource_format = kRGBResourceFormat; |
| 465 output_plane_count = 1; | 467 output_plane_count = 1; |
| 466 bits_per_channel = 8; | 468 bits_per_channel = 8; |
| 467 } | 469 } |
| 468 | 470 |
| 469 // Drop recycled resources that are the wrong format. | 471 // Drop recycled resources that are the wrong format. |
| 470 for (auto it = all_resources_.begin(); it != all_resources_.end();) { | 472 for (auto it = all_resources_.begin(); it != all_resources_.end();) { |
| 471 if (!it->has_refs() && it->resource_format() != output_resource_format) | 473 if (!it->has_refs() && it->resource_format() != output_resource_format) |
| 472 DeleteResource(it++); | 474 DeleteResource(it++); |
| 473 else | 475 else |
| (...skipping 10 matching lines...) Expand all Loading... |
| 484 output_plane_resource_size.height() > max_resource_size) { | 486 output_plane_resource_size.height() > max_resource_size) { |
| 485 // This output plane has invalid geometry. Clean up and return an empty | 487 // This output plane has invalid geometry. Clean up and return an empty |
| 486 // external resources. | 488 // external resources. |
| 487 for (ResourceList::iterator resource_it : plane_resources) | 489 for (ResourceList::iterator resource_it : plane_resources) |
| 488 resource_it->remove_ref(); | 490 resource_it->remove_ref(); |
| 489 return VideoFrameExternalResources(); | 491 return VideoFrameExternalResources(); |
| 490 } | 492 } |
| 491 | 493 |
| 492 const bool is_immutable = true; | 494 const bool is_immutable = true; |
| 493 ResourceList::iterator resource_it = RecycleOrAllocateResource( | 495 ResourceList::iterator resource_it = RecycleOrAllocateResource( |
| 494 output_plane_resource_size, output_resource_format, | 496 output_plane_resource_size, output_resource_format, output_color_space, |
| 495 video_frame->ColorSpace(), software_compositor, is_immutable, | 497 software_compositor, is_immutable, video_frame->unique_id(), i); |
| 496 video_frame->unique_id(), i); | |
| 497 | 498 |
| 498 resource_it->add_ref(); | 499 resource_it->add_ref(); |
| 499 plane_resources.push_back(resource_it); | 500 plane_resources.push_back(resource_it); |
| 500 } | 501 } |
| 501 | 502 |
| 502 VideoFrameExternalResources external_resources; | 503 VideoFrameExternalResources external_resources; |
| 503 | 504 |
| 504 external_resources.bits_per_channel = bits_per_channel; | 505 external_resources.bits_per_channel = bits_per_channel; |
| 505 | 506 |
| 506 if (software_compositor || texture_needs_rgb_conversion) { | 507 if (software_compositor || texture_needs_rgb_conversion) { |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 543 plane_resource.resource_id()); | 544 plane_resource.resource_id()); |
| 544 external_resources.software_release_callback = base::Bind( | 545 external_resources.software_release_callback = base::Bind( |
| 545 &RecycleResource, AsWeakPtr(), plane_resource.resource_id()); | 546 &RecycleResource, AsWeakPtr(), plane_resource.resource_id()); |
| 546 external_resources.type = VideoFrameExternalResources::SOFTWARE_RESOURCE; | 547 external_resources.type = VideoFrameExternalResources::SOFTWARE_RESOURCE; |
| 547 } else { | 548 } else { |
| 548 // VideoResourceUpdater shares a context with the compositor so | 549 // VideoResourceUpdater shares a context with the compositor so |
| 549 // a sync token is not required. | 550 // a sync token is not required. |
| 550 TextureMailbox mailbox(plane_resource.mailbox(), gpu::SyncToken(), | 551 TextureMailbox mailbox(plane_resource.mailbox(), gpu::SyncToken(), |
| 551 resource_provider_->GetResourceTextureTarget( | 552 resource_provider_->GetResourceTextureTarget( |
| 552 plane_resource.resource_id())); | 553 plane_resource.resource_id())); |
| 553 mailbox.set_color_space(video_frame->ColorSpace()); | 554 mailbox.set_color_space(output_color_space); |
| 554 external_resources.mailboxes.push_back(mailbox); | 555 external_resources.mailboxes.push_back(mailbox); |
| 555 external_resources.release_callbacks.push_back(base::Bind( | 556 external_resources.release_callbacks.push_back(base::Bind( |
| 556 &RecycleResource, AsWeakPtr(), plane_resource.resource_id())); | 557 &RecycleResource, AsWeakPtr(), plane_resource.resource_id())); |
| 557 external_resources.type = VideoFrameExternalResources::RGBA_RESOURCE; | 558 external_resources.type = VideoFrameExternalResources::RGBA_RESOURCE; |
| 558 } | 559 } |
| 559 return external_resources; | 560 return external_resources; |
| 560 } | 561 } |
| 561 | 562 |
| 562 std::unique_ptr<HalfFloatMaker> half_float_maker; | 563 std::unique_ptr<HalfFloatMaker> half_float_maker; |
| 563 if (resource_provider_->YuvResourceFormat(bits_per_channel) == | 564 if (resource_provider_->YuvResourceFormat(bits_per_channel) == |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 645 resource_provider_->CopyToResource(plane_resource.resource_id(), pixels, | 646 resource_provider_->CopyToResource(plane_resource.resource_id(), pixels, |
| 646 resource_size_pixels); | 647 resource_size_pixels); |
| 647 plane_resource.SetUniqueId(video_frame->unique_id(), i); | 648 plane_resource.SetUniqueId(video_frame->unique_id(), i); |
| 648 } | 649 } |
| 649 | 650 |
| 650 // VideoResourceUpdater shares a context with the compositor so a | 651 // VideoResourceUpdater shares a context with the compositor so a |
| 651 // sync token is not required. | 652 // sync token is not required. |
| 652 TextureMailbox mailbox(plane_resource.mailbox(), gpu::SyncToken(), | 653 TextureMailbox mailbox(plane_resource.mailbox(), gpu::SyncToken(), |
| 653 resource_provider_->GetResourceTextureTarget( | 654 resource_provider_->GetResourceTextureTarget( |
| 654 plane_resource.resource_id())); | 655 plane_resource.resource_id())); |
| 655 mailbox.set_color_space(video_frame->ColorSpace()); | 656 mailbox.set_color_space(output_color_space); |
| 656 external_resources.mailboxes.push_back(mailbox); | 657 external_resources.mailboxes.push_back(mailbox); |
| 657 external_resources.release_callbacks.push_back(base::Bind( | 658 external_resources.release_callbacks.push_back(base::Bind( |
| 658 &RecycleResource, AsWeakPtr(), plane_resource.resource_id())); | 659 &RecycleResource, AsWeakPtr(), plane_resource.resource_id())); |
| 659 } | 660 } |
| 660 | 661 |
| 661 external_resources.type = VideoFrameExternalResources::YUV_RESOURCE; | 662 external_resources.type = VideoFrameExternalResources::YUV_RESOURCE; |
| 662 return external_resources; | 663 return external_resources; |
| 663 } | 664 } |
| 664 | 665 |
| 665 // static | 666 // static |
| (...skipping 12 matching lines...) Expand all Loading... |
| 678 // |video_frame|'s previous sync point using the current GL context. | 679 // |video_frame|'s previous sync point using the current GL context. |
| 679 SyncTokenClientImpl client(updater->context_provider_->ContextGL(), | 680 SyncTokenClientImpl client(updater->context_provider_->ContextGL(), |
| 680 sync_token); | 681 sync_token); |
| 681 video_frame->UpdateReleaseSyncToken(&client); | 682 video_frame->UpdateReleaseSyncToken(&client); |
| 682 } | 683 } |
| 683 | 684 |
| 684 // Create a copy of a texture-backed source video frame in a new GL_TEXTURE_2D | 685 // Create a copy of a texture-backed source video frame in a new GL_TEXTURE_2D |
| 685 // texture. | 686 // texture. |
| 686 void VideoResourceUpdater::CopyPlaneTexture( | 687 void VideoResourceUpdater::CopyPlaneTexture( |
| 687 media::VideoFrame* video_frame, | 688 media::VideoFrame* video_frame, |
| 689 const gfx::ColorSpace& resource_color_space, |
| 688 const gpu::MailboxHolder& mailbox_holder, | 690 const gpu::MailboxHolder& mailbox_holder, |
| 689 VideoFrameExternalResources* external_resources) { | 691 VideoFrameExternalResources* external_resources) { |
| 690 gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL(); | 692 gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL(); |
| 691 SyncTokenClientImpl client(gl, mailbox_holder.sync_token); | 693 SyncTokenClientImpl client(gl, mailbox_holder.sync_token); |
| 692 | 694 |
| 693 const gfx::Size output_plane_resource_size = video_frame->coded_size(); | 695 const gfx::Size output_plane_resource_size = video_frame->coded_size(); |
| 694 // The copy needs to be a direct transfer of pixel data, so we use an RGBA8 | 696 // The copy needs to be a direct transfer of pixel data, so we use an RGBA8 |
| 695 // target to avoid loss of precision or dropping any alpha component. | 697 // target to avoid loss of precision or dropping any alpha component. |
| 696 const ResourceFormat copy_target_format = ResourceFormat::RGBA_8888; | 698 const ResourceFormat copy_target_format = ResourceFormat::RGBA_8888; |
| 697 | 699 |
| 698 const bool is_immutable = false; | 700 const bool is_immutable = false; |
| 699 const int no_unique_id = 0; | 701 const int no_unique_id = 0; |
| 700 const int no_plane_index = -1; // Do not recycle referenced textures. | 702 const int no_plane_index = -1; // Do not recycle referenced textures. |
| 701 VideoResourceUpdater::ResourceList::iterator resource = | 703 VideoResourceUpdater::ResourceList::iterator resource = |
| 702 RecycleOrAllocateResource(output_plane_resource_size, copy_target_format, | 704 RecycleOrAllocateResource(output_plane_resource_size, copy_target_format, |
| 703 video_frame->ColorSpace(), false, is_immutable, | 705 resource_color_space, false, is_immutable, |
| 704 no_unique_id, no_plane_index); | 706 no_unique_id, no_plane_index); |
| 705 resource->add_ref(); | 707 resource->add_ref(); |
| 706 | 708 |
| 707 ResourceProvider::ScopedWriteLockGL lock(resource_provider_, | 709 ResourceProvider::ScopedWriteLockGL lock(resource_provider_, |
| 708 resource->resource_id(), false); | 710 resource->resource_id(), false); |
| 709 DCHECK_EQ( | 711 DCHECK_EQ( |
| 710 resource_provider_->GetResourceTextureTarget(resource->resource_id()), | 712 resource_provider_->GetResourceTextureTarget(resource->resource_id()), |
| 711 (GLenum)GL_TEXTURE_2D); | 713 (GLenum)GL_TEXTURE_2D); |
| 712 | 714 |
| 713 gl->WaitSyncTokenCHROMIUM(mailbox_holder.sync_token.GetConstData()); | 715 gl->WaitSyncTokenCHROMIUM(mailbox_holder.sync_token.GetConstData()); |
| 714 uint32_t src_texture_id = gl->CreateAndConsumeTextureCHROMIUM( | 716 uint32_t src_texture_id = gl->CreateAndConsumeTextureCHROMIUM( |
| 715 mailbox_holder.texture_target, mailbox_holder.mailbox.name); | 717 mailbox_holder.texture_target, mailbox_holder.mailbox.name); |
| 716 gl->CopySubTextureCHROMIUM( | 718 gl->CopySubTextureCHROMIUM( |
| 717 src_texture_id, 0, GL_TEXTURE_2D, lock.texture_id(), 0, 0, 0, 0, 0, | 719 src_texture_id, 0, GL_TEXTURE_2D, lock.texture_id(), 0, 0, 0, 0, 0, |
| 718 output_plane_resource_size.width(), output_plane_resource_size.height(), | 720 output_plane_resource_size.width(), output_plane_resource_size.height(), |
| 719 false, false, false); | 721 false, false, false); |
| 720 gl->DeleteTextures(1, &src_texture_id); | 722 gl->DeleteTextures(1, &src_texture_id); |
| 721 | 723 |
| 722 // Done with the source video frame texture at this point. | 724 // Done with the source video frame texture at this point. |
| 723 video_frame->UpdateReleaseSyncToken(&client); | 725 video_frame->UpdateReleaseSyncToken(&client); |
| 724 | 726 |
| 725 // VideoResourceUpdater shares a context with the compositor so a | 727 // VideoResourceUpdater shares a context with the compositor so a |
| 726 // sync token is not required. | 728 // sync token is not required. |
| 727 TextureMailbox mailbox(resource->mailbox(), gpu::SyncToken(), GL_TEXTURE_2D, | 729 TextureMailbox mailbox(resource->mailbox(), gpu::SyncToken(), GL_TEXTURE_2D, |
| 728 video_frame->coded_size(), false, false); | 730 video_frame->coded_size(), false, false); |
| 729 mailbox.set_color_space(video_frame->ColorSpace()); | 731 mailbox.set_color_space(resource_color_space); |
| 730 external_resources->mailboxes.push_back(mailbox); | 732 external_resources->mailboxes.push_back(mailbox); |
| 731 | 733 |
| 732 external_resources->release_callbacks.push_back( | 734 external_resources->release_callbacks.push_back( |
| 733 base::Bind(&RecycleResource, AsWeakPtr(), resource->resource_id())); | 735 base::Bind(&RecycleResource, AsWeakPtr(), resource->resource_id())); |
| 734 } | 736 } |
| 735 | 737 |
| 736 VideoFrameExternalResources VideoResourceUpdater::CreateForHardwarePlanes( | 738 VideoFrameExternalResources VideoResourceUpdater::CreateForHardwarePlanes( |
| 737 scoped_refptr<media::VideoFrame> video_frame) { | 739 scoped_refptr<media::VideoFrame> video_frame) { |
| 738 TRACE_EVENT0("cc", "VideoResourceUpdater::CreateForHardwarePlanes"); | 740 TRACE_EVENT0("cc", "VideoResourceUpdater::CreateForHardwarePlanes"); |
| 739 DCHECK(video_frame->HasTextures()); | 741 DCHECK(video_frame->HasTextures()); |
| 740 if (!context_provider_) | 742 if (!context_provider_) |
| 741 return VideoFrameExternalResources(); | 743 return VideoFrameExternalResources(); |
| 742 | 744 |
| 743 VideoFrameExternalResources external_resources; | 745 VideoFrameExternalResources external_resources; |
| 744 if (video_frame->metadata()->IsTrue( | 746 if (video_frame->metadata()->IsTrue( |
| 745 media::VideoFrameMetadata::READ_LOCK_FENCES_ENABLED)) { | 747 media::VideoFrameMetadata::READ_LOCK_FENCES_ENABLED)) { |
| 746 external_resources.read_lock_fences_enabled = true; | 748 external_resources.read_lock_fences_enabled = true; |
| 747 } | 749 } |
| 750 gfx::ColorSpace resource_color_space = video_frame->ColorSpace(); |
| 748 | 751 |
| 749 external_resources.type = ResourceTypeForVideoFrame(video_frame.get()); | 752 external_resources.type = ResourceTypeForVideoFrame(video_frame.get()); |
| 750 if (external_resources.type == VideoFrameExternalResources::NONE) { | 753 if (external_resources.type == VideoFrameExternalResources::NONE) { |
| 751 DLOG(ERROR) << "Unsupported Texture format" | 754 DLOG(ERROR) << "Unsupported Texture format" |
| 752 << media::VideoPixelFormatToString(video_frame->format()); | 755 << media::VideoPixelFormatToString(video_frame->format()); |
| 753 return external_resources; | 756 return external_resources; |
| 754 } | 757 } |
| 758 if (external_resources.type == VideoFrameExternalResources::YUV_RESOURCE) |
| 759 resource_color_space = resource_color_space.GetAsFullRangeRGB(); |
| 755 | 760 |
| 756 const size_t num_planes = media::VideoFrame::NumPlanes(video_frame->format()); | 761 const size_t num_planes = media::VideoFrame::NumPlanes(video_frame->format()); |
| 757 for (size_t i = 0; i < num_planes; ++i) { | 762 for (size_t i = 0; i < num_planes; ++i) { |
| 758 const gpu::MailboxHolder& mailbox_holder = video_frame->mailbox_holder(i); | 763 const gpu::MailboxHolder& mailbox_holder = video_frame->mailbox_holder(i); |
| 759 if (mailbox_holder.mailbox.IsZero()) | 764 if (mailbox_holder.mailbox.IsZero()) |
| 760 break; | 765 break; |
| 761 | 766 |
| 762 if (video_frame->metadata()->IsTrue( | 767 if (video_frame->metadata()->IsTrue( |
| 763 media::VideoFrameMetadata::COPY_REQUIRED)) { | 768 media::VideoFrameMetadata::COPY_REQUIRED)) { |
| 764 CopyPlaneTexture(video_frame.get(), mailbox_holder, &external_resources); | 769 CopyPlaneTexture(video_frame.get(), resource_color_space, mailbox_holder, |
| 770 &external_resources); |
| 765 } else { | 771 } else { |
| 766 TextureMailbox mailbox(mailbox_holder.mailbox, mailbox_holder.sync_token, | 772 TextureMailbox mailbox(mailbox_holder.mailbox, mailbox_holder.sync_token, |
| 767 mailbox_holder.texture_target, | 773 mailbox_holder.texture_target, |
| 768 video_frame->coded_size(), | 774 video_frame->coded_size(), |
| 769 video_frame->metadata()->IsTrue( | 775 video_frame->metadata()->IsTrue( |
| 770 media::VideoFrameMetadata::ALLOW_OVERLAY), | 776 media::VideoFrameMetadata::ALLOW_OVERLAY), |
| 771 false); | 777 false); |
| 772 mailbox.set_color_space(video_frame->ColorSpace()); | 778 mailbox.set_color_space(resource_color_space); |
| 773 #if defined(OS_ANDROID) | 779 #if defined(OS_ANDROID) |
| 774 mailbox.set_is_backed_by_surface_texture(video_frame->metadata()->IsTrue( | 780 mailbox.set_is_backed_by_surface_texture(video_frame->metadata()->IsTrue( |
| 775 media::VideoFrameMetadata::SURFACE_TEXTURE)); | 781 media::VideoFrameMetadata::SURFACE_TEXTURE)); |
| 776 mailbox.set_wants_promotion_hint(video_frame->metadata()->IsTrue( | 782 mailbox.set_wants_promotion_hint(video_frame->metadata()->IsTrue( |
| 777 media::VideoFrameMetadata::WANTS_PROMOTION_HINT)); | 783 media::VideoFrameMetadata::WANTS_PROMOTION_HINT)); |
| 778 #endif | 784 #endif |
| 779 external_resources.mailboxes.push_back(mailbox); | 785 external_resources.mailboxes.push_back(mailbox); |
| 780 external_resources.release_callbacks.push_back( | 786 external_resources.release_callbacks.push_back( |
| 781 base::Bind(&ReturnTexture, AsWeakPtr(), video_frame)); | 787 base::Bind(&ReturnTexture, AsWeakPtr(), video_frame)); |
| 782 } | 788 } |
| (...skipping 29 matching lines...) Expand all Loading... |
| 812 if (lost_resource) { | 818 if (lost_resource) { |
| 813 resource_it->clear_refs(); | 819 resource_it->clear_refs(); |
| 814 updater->DeleteResource(resource_it); | 820 updater->DeleteResource(resource_it); |
| 815 return; | 821 return; |
| 816 } | 822 } |
| 817 | 823 |
| 818 resource_it->remove_ref(); | 824 resource_it->remove_ref(); |
| 819 } | 825 } |
| 820 | 826 |
| 821 } // namespace cc | 827 } // namespace cc |
| OLD | NEW |