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 361 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
372 VideoResourceUpdater::NewHalfFloatMaker(int bits_per_channel) { | 372 VideoResourceUpdater::NewHalfFloatMaker(int bits_per_channel) { |
373 if (bits_per_channel < 11) { | 373 if (bits_per_channel < 11) { |
374 return std::unique_ptr<VideoResourceUpdater::HalfFloatMaker>( | 374 return std::unique_ptr<VideoResourceUpdater::HalfFloatMaker>( |
375 new HalfFloatMaker_xor(bits_per_channel)); | 375 new HalfFloatMaker_xor(bits_per_channel)); |
376 } else { | 376 } else { |
377 return std::unique_ptr<VideoResourceUpdater::HalfFloatMaker>( | 377 return std::unique_ptr<VideoResourceUpdater::HalfFloatMaker>( |
378 new HalfFloatMaker_libyuv(bits_per_channel)); | 378 new HalfFloatMaker_libyuv(bits_per_channel)); |
379 } | 379 } |
380 } | 380 } |
381 | 381 |
| 382 ResourceFormat VideoResourceUpdater::YuvResourceFormat( |
| 383 int bits, |
| 384 media::VideoPixelFormat format) const { |
| 385 if (!context_provider_) |
| 386 return RGBA_8888; |
| 387 |
| 388 if (format == media::PIXEL_FORMAT_Y16) { |
| 389 // Unable to display directly as yuv planes so convert it to RGBA for |
| 390 // compositing. |
| 391 return RGBA_8888; |
| 392 } |
| 393 |
| 394 const auto caps = context_provider_->ContextCapabilities(); |
| 395 if (caps.disable_one_component_textures) |
| 396 return RGBA_8888; |
| 397 |
| 398 ResourceFormat yuv_resource_format = caps.texture_rg ? RED_8 : LUMINANCE_8; |
| 399 if (bits <= 8) |
| 400 return yuv_resource_format; |
| 401 |
| 402 if (caps.texture_half_float_linear) |
| 403 return LUMINANCE_F16; |
| 404 |
| 405 return yuv_resource_format; |
| 406 } |
| 407 |
382 VideoFrameExternalResources VideoResourceUpdater::CreateForSoftwarePlanes( | 408 VideoFrameExternalResources VideoResourceUpdater::CreateForSoftwarePlanes( |
383 scoped_refptr<media::VideoFrame> video_frame) { | 409 scoped_refptr<media::VideoFrame> video_frame) { |
384 TRACE_EVENT0("cc", "VideoResourceUpdater::CreateForSoftwarePlanes"); | 410 TRACE_EVENT0("cc", "VideoResourceUpdater::CreateForSoftwarePlanes"); |
385 const media::VideoPixelFormat input_frame_format = video_frame->format(); | 411 const media::VideoPixelFormat input_frame_format = video_frame->format(); |
386 | 412 |
387 // TODO(hubbe): Make this a video frame method. | 413 // TODO(hubbe): Make this a video frame method. |
388 int bits_per_channel = 0; | 414 int bits_per_channel = 0; |
389 switch (input_frame_format) { | 415 switch (input_frame_format) { |
390 case media::PIXEL_FORMAT_UNKNOWN: | 416 case media::PIXEL_FORMAT_UNKNOWN: |
391 NOTREACHED(); | 417 NOTREACHED(); |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
425 break; | 451 break; |
426 case media::PIXEL_FORMAT_Y16: | 452 case media::PIXEL_FORMAT_Y16: |
427 bits_per_channel = 16; | 453 bits_per_channel = 16; |
428 break; | 454 break; |
429 } | 455 } |
430 | 456 |
431 // Only YUV and Y16 software video frames are supported. | 457 // Only YUV and Y16 software video frames are supported. |
432 DCHECK(media::IsYuvPlanar(input_frame_format) || | 458 DCHECK(media::IsYuvPlanar(input_frame_format) || |
433 input_frame_format == media::PIXEL_FORMAT_Y16); | 459 input_frame_format == media::PIXEL_FORMAT_Y16); |
434 | 460 |
435 const bool software_compositor = context_provider_ == NULL; | 461 const bool software_compositor = context_provider_ == nullptr; |
| 462 bool disable_one_component_textures = true; |
| 463 if (!software_compositor) { |
| 464 const auto caps = context_provider_->ContextCapabilities(); |
| 465 disable_one_component_textures = caps.disable_one_component_textures; |
| 466 } |
436 | 467 |
437 ResourceFormat output_resource_format; | 468 ResourceFormat output_resource_format = |
438 if (input_frame_format == media::PIXEL_FORMAT_Y16) { | 469 YuvResourceFormat(bits_per_channel, input_frame_format); |
439 // Unable to display directly as yuv planes so convert it to RGBA for | |
440 // compositing. | |
441 output_resource_format = RGBA_8888; | |
442 } else { | |
443 // Can be composited directly from yuv planes. | |
444 output_resource_format = | |
445 resource_provider_->YuvResourceFormat(bits_per_channel); | |
446 } | |
447 | 470 |
448 // If GPU compositing is enabled, but the output resource format | 471 // If GPU compositing is enabled, but the output resource format |
449 // returned by the resource provider is RGBA_8888, then a GPU driver | 472 // returned by the resource provider is RGBA_8888, then a GPU driver |
450 // bug workaround requires that YUV frames must be converted to RGB | 473 // bug workaround requires that YUV frames must be converted to RGB |
451 // before texture upload. | 474 // before texture upload. |
452 bool texture_needs_rgb_conversion = | 475 bool texture_needs_rgb_conversion = |
453 !software_compositor && | 476 (!software_compositor && disable_one_component_textures) || |
454 output_resource_format == ResourceFormat::RGBA_8888; | 477 input_frame_format == media::PIXEL_FORMAT_Y16; |
455 size_t output_plane_count = media::VideoFrame::NumPlanes(input_frame_format); | 478 size_t output_plane_count = media::VideoFrame::NumPlanes(input_frame_format); |
456 | 479 |
457 // TODO(skaslev): If we're in software compositing mode, we do the YUV -> RGB | 480 // TODO(skaslev): If we're in software compositing mode, we do the YUV -> RGB |
458 // conversion here. That involves an extra copy of each frame to a bitmap. | 481 // conversion here. That involves an extra copy of each frame to a bitmap. |
459 // Obviously, this is suboptimal and should be addressed once ubercompositor | 482 // Obviously, this is suboptimal and should be addressed once ubercompositor |
460 // starts shaping up. | 483 // starts shaping up. |
461 if (software_compositor || texture_needs_rgb_conversion) { | 484 if (software_compositor || texture_needs_rgb_conversion) { |
462 output_resource_format = kRGBResourceFormat; | 485 DCHECK_EQ(output_resource_format, kRGBResourceFormat); |
463 output_plane_count = 1; | 486 output_plane_count = 1; |
464 bits_per_channel = 8; | 487 bits_per_channel = 8; |
465 } | 488 } |
466 | 489 |
467 // Drop recycled resources that are the wrong format. | 490 // Drop recycled resources that are the wrong format. |
468 for (auto it = all_resources_.begin(); it != all_resources_.end();) { | 491 for (auto it = all_resources_.begin(); it != all_resources_.end();) { |
469 if (!it->has_refs() && it->resource_format() != output_resource_format) | 492 if (!it->has_refs() && it->resource_format() != output_resource_format) |
470 DeleteResource(it++); | 493 DeleteResource(it++); |
471 else | 494 else |
472 ++it; | 495 ++it; |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
520 // by software. | 543 // by software. |
521 video_renderer_->Copy(video_frame, &canvas, media::Context3D()); | 544 video_renderer_->Copy(video_frame, &canvas, media::Context3D()); |
522 } else { | 545 } else { |
523 size_t bytes_per_row = ResourceUtil::CheckedWidthInBytes<size_t>( | 546 size_t bytes_per_row = ResourceUtil::CheckedWidthInBytes<size_t>( |
524 video_frame->coded_size().width(), ResourceFormat::RGBA_8888); | 547 video_frame->coded_size().width(), ResourceFormat::RGBA_8888); |
525 size_t needed_size = bytes_per_row * video_frame->coded_size().height(); | 548 size_t needed_size = bytes_per_row * video_frame->coded_size().height(); |
526 if (upload_pixels_.size() < needed_size) | 549 if (upload_pixels_.size() < needed_size) |
527 upload_pixels_.resize(needed_size); | 550 upload_pixels_.resize(needed_size); |
528 | 551 |
529 media::SkCanvasVideoRenderer::ConvertVideoFrameToRGBPixels( | 552 media::SkCanvasVideoRenderer::ConvertVideoFrameToRGBPixels( |
530 video_frame.get(), &upload_pixels_[0], bytes_per_row); | 553 video_frame.get(), |
| 554 media::SkCanvasVideoRenderer::ConvertingSize::CODED, |
| 555 &upload_pixels_[0], bytes_per_row); |
531 | 556 |
532 resource_provider_->CopyToResource(plane_resource.resource_id(), | 557 resource_provider_->CopyToResource(plane_resource.resource_id(), |
533 &upload_pixels_[0], | 558 &upload_pixels_[0], |
534 plane_resource.resource_size()); | 559 plane_resource.resource_size()); |
535 } | 560 } |
536 plane_resource.SetUniqueId(video_frame->unique_id(), 0); | 561 plane_resource.SetUniqueId(video_frame->unique_id(), 0); |
537 } | 562 } |
538 | 563 |
539 if (software_compositor) { | 564 if (software_compositor) { |
540 external_resources.software_resources.push_back( | 565 external_resources.software_resources.push_back( |
541 plane_resource.resource_id()); | 566 plane_resource.resource_id()); |
542 external_resources.software_release_callback = base::Bind( | 567 external_resources.software_release_callback = base::Bind( |
543 &RecycleResource, AsWeakPtr(), plane_resource.resource_id()); | 568 &RecycleResource, AsWeakPtr(), plane_resource.resource_id()); |
544 external_resources.type = VideoFrameExternalResources::SOFTWARE_RESOURCE; | 569 external_resources.type = VideoFrameExternalResources::SOFTWARE_RESOURCE; |
545 } else { | 570 } else { |
546 // VideoResourceUpdater shares a context with the compositor so | 571 // VideoResourceUpdater shares a context with the compositor so |
547 // a sync token is not required. | 572 // a sync token is not required. |
548 TextureMailbox mailbox(plane_resource.mailbox(), gpu::SyncToken(), | 573 TextureMailbox mailbox(plane_resource.mailbox(), gpu::SyncToken(), |
549 resource_provider_->GetResourceTextureTarget( | 574 resource_provider_->GetResourceTextureTarget( |
550 plane_resource.resource_id())); | 575 plane_resource.resource_id()), |
| 576 plane_resource.resource_size(), false, false); |
551 mailbox.set_color_space(video_frame->ColorSpace()); | 577 mailbox.set_color_space(video_frame->ColorSpace()); |
552 external_resources.mailboxes.push_back(mailbox); | 578 external_resources.mailboxes.push_back(mailbox); |
553 external_resources.release_callbacks.push_back(base::Bind( | 579 external_resources.release_callbacks.push_back(base::Bind( |
554 &RecycleResource, AsWeakPtr(), plane_resource.resource_id())); | 580 &RecycleResource, AsWeakPtr(), plane_resource.resource_id())); |
555 external_resources.type = VideoFrameExternalResources::RGBA_RESOURCE; | 581 external_resources.type = VideoFrameExternalResources::RGBA_RESOURCE; |
556 } | 582 } |
557 return external_resources; | 583 return external_resources; |
558 } | 584 } |
559 | 585 |
560 std::unique_ptr<HalfFloatMaker> half_float_maker; | 586 std::unique_ptr<HalfFloatMaker> half_float_maker; |
561 if (resource_provider_->YuvResourceFormat(bits_per_channel) == | 587 if (YuvResourceFormat(bits_per_channel, input_frame_format) == |
562 LUMINANCE_F16) { | 588 LUMINANCE_F16) { |
563 half_float_maker = NewHalfFloatMaker(bits_per_channel); | 589 half_float_maker = NewHalfFloatMaker(bits_per_channel); |
564 external_resources.offset = half_float_maker->Offset(); | 590 external_resources.offset = half_float_maker->Offset(); |
565 external_resources.multiplier = half_float_maker->Multiplier(); | 591 external_resources.multiplier = half_float_maker->Multiplier(); |
566 } | 592 } |
567 | 593 |
568 for (size_t i = 0; i < plane_resources.size(); ++i) { | 594 for (size_t i = 0; i < plane_resources.size(); ++i) { |
569 PlaneResource& plane_resource = *plane_resources[i]; | 595 PlaneResource& plane_resource = *plane_resources[i]; |
570 // Update each plane's resource id with its content. | 596 // Update each plane's resource id with its content. |
571 DCHECK_EQ(plane_resource.resource_format(), | 597 DCHECK_EQ(plane_resource.resource_format(), |
572 resource_provider_->YuvResourceFormat(bits_per_channel)); | 598 YuvResourceFormat(bits_per_channel, input_frame_format)); |
573 | 599 |
574 if (!plane_resource.Matches(video_frame->unique_id(), i)) { | 600 if (!plane_resource.Matches(video_frame->unique_id(), i)) { |
575 // TODO(hubbe): Move all conversion (and upload?) code to media/. | 601 // TODO(hubbe): Move all conversion (and upload?) code to media/. |
576 // We need to transfer data from |video_frame| to the plane resource. | 602 // We need to transfer data from |video_frame| to the plane resource. |
577 // TODO(reveman): Can use GpuMemoryBuffers here to improve performance. | 603 // TODO(reveman): Can use GpuMemoryBuffers here to improve performance. |
578 | 604 |
579 // The |resource_size_pixels| is the size of the resource we want to | 605 // The |resource_size_pixels| is the size of the resource we want to |
580 // upload to. | 606 // upload to. |
581 gfx::Size resource_size_pixels = plane_resource.resource_size(); | 607 gfx::Size resource_size_pixels = plane_resource.resource_size(); |
582 // The |video_stride_bytes| is the width of the video frame we are | 608 // The |video_stride_bytes| is the width of the video frame we are |
(...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
804 if (lost_resource) { | 830 if (lost_resource) { |
805 resource_it->clear_refs(); | 831 resource_it->clear_refs(); |
806 updater->DeleteResource(resource_it); | 832 updater->DeleteResource(resource_it); |
807 return; | 833 return; |
808 } | 834 } |
809 | 835 |
810 resource_it->remove_ref(); | 836 resource_it->remove_ref(); |
811 } | 837 } |
812 | 838 |
813 } // namespace cc | 839 } // namespace cc |
OLD | NEW |