|
5 | 5 |
|
6 | 6 | #include "ExternalTexture.h" |
7 | 7 |
|
| 8 | +#include "Colorspaces.h" |
8 | 9 | #include "ImageContainer.h" |
9 | 10 | #include "mozilla/Assertions.h" |
10 | 11 | #include "mozilla/ErrorResult.h" |
|
14 | 15 | #include "mozilla/gfx/Logging.h" |
15 | 16 | #include "mozilla/layers/ImageDataSerializer.h" |
16 | 17 | #include "mozilla/webgpu/Queue.h" |
| 18 | +#include "mozilla/webgpu/Utility.h" |
17 | 19 | #include "mozilla/webgpu/WebGPUChild.h" |
18 | 20 | #include "mozilla/webgpu/WebGPUParent.h" |
19 | 21 | #include "nsLayoutUtils.h" |
20 | 22 | #include "nsPrintfCString.h" |
21 | 23 |
|
22 | 24 | namespace mozilla::webgpu { |
23 | 25 |
|
24 | | -GPU_IMPL_CYCLE_COLLECTION(ExternalTexture, mGlobal) |
| 26 | +GPU_IMPL_CYCLE_COLLECTION(ExternalTexture, mParent) |
| 27 | +GPU_IMPL_JS_WRAP(ExternalTexture) |
25 | 28 |
|
26 | | -JSObject* ExternalTexture::WrapObject(JSContext* cx, |
27 | | - JS ::Handle<JSObject*> givenProto) { |
28 | | - return dom::GPUExternalTexture_Binding::Wrap(cx, this, givenProto); |
| 29 | +ExternalTexture::ExternalTexture(Device* const aParent, RawId aId, |
| 30 | + RefPtr<ExternalTextureSourceClient> aSource) |
| 31 | + : ChildOf(aParent), mId(aId), mSource(aSource) { |
| 32 | + MOZ_RELEASE_ASSERT(aId); |
| 33 | +} |
| 34 | + |
| 35 | +/* static */ already_AddRefed<ExternalTexture> ExternalTexture::Create( |
| 36 | + Device* const aParent, const nsString& aLabel, |
| 37 | + const RefPtr<ExternalTextureSourceClient>& aSource, |
| 38 | + dom::PredefinedColorSpace aColorSpace) { |
| 39 | + const webgpu::StringHelper label(aLabel); |
| 40 | + const ffi::WGPUPredefinedColorSpace colorSpace = |
| 41 | + ConvertPredefinedColorSpace(aColorSpace); |
| 42 | + const ffi::WGPUExternalTextureDescriptor desc = { |
| 43 | + .label = label.Get(), |
| 44 | + .source = aSource ? aSource->mId : 0, |
| 45 | + .color_space = colorSpace, |
| 46 | + }; |
| 47 | + |
| 48 | + const RawId id = ffi::wgpu_client_create_external_texture( |
| 49 | + aParent->GetBridge()->GetClient(), aParent->mId, &desc); |
| 50 | + |
| 51 | + RefPtr<ExternalTexture> externalTexture = |
| 52 | + new ExternalTexture(aParent, id, aSource); |
| 53 | + externalTexture->SetLabel(aLabel); |
| 54 | + |
| 55 | + return externalTexture.forget(); |
| 56 | +} |
| 57 | + |
| 58 | +void ExternalTexture::Cleanup() { |
| 59 | + if (!mValid) { |
| 60 | + return; |
| 61 | + } |
| 62 | + mValid = false; |
| 63 | + |
| 64 | + mSource = nullptr; |
| 65 | + |
| 66 | + auto bridge = mParent->GetBridge(); |
| 67 | + if (!bridge) { |
| 68 | + return; |
| 69 | + } |
| 70 | + |
| 71 | + ffi::wgpu_client_drop_external_texture(bridge->GetClient(), mId); |
29 | 72 | } |
30 | 73 |
|
| 74 | +ExternalTexture::~ExternalTexture() { Cleanup(); } |
| 75 | + |
31 | 76 | ExternalTextureSourceClient::ExternalTextureSourceClient( |
32 | 77 | WebGPUChild* aBridge, RawId aId, const std::array<RawId, 3>& aTextureIds, |
33 | 78 | const std::array<RawId, 3>& aViewIds) |
@@ -446,4 +491,198 @@ ExternalTextureSourceHost::CreateError() { |
446 | 491 | gfx::YUVRangedColorSpace::GbrIdentity, {}, {}); |
447 | 492 | } |
448 | 493 |
|
| 494 | +static color::ColorspaceTransform GetColorSpaceTransform( |
| 495 | + gfx::YUVRangedColorSpace aSrcColorSpace, |
| 496 | + ffi::WGPUPredefinedColorSpace aDestColorSpace) { |
| 497 | + const bool rec709GammaAsSrgb = |
| 498 | + StaticPrefs::gfx_color_management_rec709_gamma_as_srgb(); |
| 499 | + const bool rec2020GammaAsRec709 = |
| 500 | + StaticPrefs::gfx_color_management_rec2020_gamma_as_rec709(); |
| 501 | + |
| 502 | + color::ColorspaceDesc srcColorSpace; |
| 503 | + switch (aSrcColorSpace) { |
| 504 | + case gfx::YUVRangedColorSpace::BT601_Narrow: |
| 505 | + srcColorSpace = { |
| 506 | + .chrom = color::Chromaticities::Rec601_525_Ntsc(), |
| 507 | + .tf = rec709GammaAsSrgb ? color::PiecewiseGammaDesc::Srgb() |
| 508 | + : color::PiecewiseGammaDesc::Rec709(), |
| 509 | + .yuv = |
| 510 | + color::YuvDesc{ |
| 511 | + .yCoeffs = color::YuvLumaCoeffs::Rec601(), |
| 512 | + .ycbcr = color::YcbcrDesc::Narrow8(), |
| 513 | + }, |
| 514 | + }; |
| 515 | + break; |
| 516 | + case gfx::YUVRangedColorSpace::BT601_Full: |
| 517 | + srcColorSpace = { |
| 518 | + .chrom = color::Chromaticities::Rec601_525_Ntsc(), |
| 519 | + .tf = rec709GammaAsSrgb ? color::PiecewiseGammaDesc::Srgb() |
| 520 | + : color::PiecewiseGammaDesc::Rec709(), |
| 521 | + .yuv = |
| 522 | + color::YuvDesc{ |
| 523 | + .yCoeffs = color::YuvLumaCoeffs::Rec601(), |
| 524 | + .ycbcr = color::YcbcrDesc::Full8(), |
| 525 | + }, |
| 526 | + }; |
| 527 | + break; |
| 528 | + case gfx::YUVRangedColorSpace::BT709_Narrow: |
| 529 | + srcColorSpace = { |
| 530 | + .chrom = color::Chromaticities::Rec709(), |
| 531 | + .tf = rec709GammaAsSrgb ? color::PiecewiseGammaDesc::Srgb() |
| 532 | + : color::PiecewiseGammaDesc::Rec709(), |
| 533 | + .yuv = |
| 534 | + color::YuvDesc{ |
| 535 | + .yCoeffs = color::YuvLumaCoeffs::Rec709(), |
| 536 | + .ycbcr = color::YcbcrDesc::Narrow8(), |
| 537 | + }, |
| 538 | + }; |
| 539 | + break; |
| 540 | + case gfx::YUVRangedColorSpace::BT709_Full: |
| 541 | + srcColorSpace = { |
| 542 | + .chrom = color::Chromaticities::Rec709(), |
| 543 | + .tf = rec709GammaAsSrgb ? color::PiecewiseGammaDesc::Srgb() |
| 544 | + : color::PiecewiseGammaDesc::Rec709(), |
| 545 | + .yuv = |
| 546 | + color::YuvDesc{ |
| 547 | + .yCoeffs = color::YuvLumaCoeffs::Rec709(), |
| 548 | + .ycbcr = color::YcbcrDesc::Full8(), |
| 549 | + }, |
| 550 | + }; |
| 551 | + break; |
| 552 | + case gfx::YUVRangedColorSpace::BT2020_Narrow: |
| 553 | + srcColorSpace = { |
| 554 | + .chrom = color::Chromaticities::Rec2020(), |
| 555 | + .tf = rec2020GammaAsRec709 && rec709GammaAsSrgb |
| 556 | + ? color::PiecewiseGammaDesc::Srgb() |
| 557 | + : (rec2020GammaAsRec709 |
| 558 | + ? color::PiecewiseGammaDesc::Rec709() |
| 559 | + : color::PiecewiseGammaDesc::Rec2020_12bit()), |
| 560 | + .yuv = |
| 561 | + color::YuvDesc{ |
| 562 | + .yCoeffs = color::YuvLumaCoeffs::Rec2020(), |
| 563 | + .ycbcr = color::YcbcrDesc::Narrow8(), |
| 564 | + }, |
| 565 | + }; |
| 566 | + break; |
| 567 | + case gfx::YUVRangedColorSpace::BT2020_Full: |
| 568 | + srcColorSpace = { |
| 569 | + .chrom = color::Chromaticities::Rec2020(), |
| 570 | + .tf = rec2020GammaAsRec709 && rec709GammaAsSrgb |
| 571 | + ? color::PiecewiseGammaDesc::Srgb() |
| 572 | + : (rec2020GammaAsRec709 |
| 573 | + ? color::PiecewiseGammaDesc::Rec709() |
| 574 | + : color::PiecewiseGammaDesc::Rec2020_12bit()), |
| 575 | + .yuv = |
| 576 | + color::YuvDesc{ |
| 577 | + .yCoeffs = color::YuvLumaCoeffs::Rec2020(), |
| 578 | + .ycbcr = color::YcbcrDesc::Full8(), |
| 579 | + }, |
| 580 | + }; |
| 581 | + break; |
| 582 | + case gfx::YUVRangedColorSpace::GbrIdentity: |
| 583 | + srcColorSpace = { |
| 584 | + .chrom = color::Chromaticities::Rec709(), |
| 585 | + .tf = color::PiecewiseGammaDesc::Rec709(), |
| 586 | + .yuv = |
| 587 | + color::YuvDesc{ |
| 588 | + .yCoeffs = color::YuvLumaCoeffs::Gbr(), |
| 589 | + .ycbcr = color::YcbcrDesc::Full8(), |
| 590 | + }, |
| 591 | + }; |
| 592 | + break; |
| 593 | + } |
| 594 | + |
| 595 | + color::ColorspaceDesc destColorSpace{}; |
| 596 | + switch (aDestColorSpace) { |
| 597 | + case ffi::WGPUPredefinedColorSpace_Srgb: |
| 598 | + destColorSpace = {.chrom = color::Chromaticities::Srgb(), |
| 599 | + .tf = color::PiecewiseGammaDesc::Srgb()}; |
| 600 | + break; |
| 601 | + case ffi::WGPUPredefinedColorSpace_DisplayP3: |
| 602 | + destColorSpace = {.chrom = color::Chromaticities::DisplayP3(), |
| 603 | + .tf = color::PiecewiseGammaDesc::DisplayP3()}; |
| 604 | + break; |
| 605 | + case ffi::WGPUPredefinedColorSpace_Sentinel: |
| 606 | + MOZ_CRASH("Invalid WGPUPredefinedColorSpace"); |
| 607 | + } |
| 608 | + |
| 609 | + return color::ColorspaceTransform::Create(srcColorSpace, destColorSpace); |
| 610 | +} |
| 611 | + |
| 612 | +static ffi::WGPUExternalTextureFormat MapFormat(gfx::SurfaceFormat aFormat) { |
| 613 | + switch (aFormat) { |
| 614 | + case gfx::SurfaceFormat::B8G8R8A8: |
| 615 | + case gfx::SurfaceFormat::B8G8R8X8: |
| 616 | + case gfx::SurfaceFormat::R8G8B8A8: |
| 617 | + case gfx::SurfaceFormat::R8G8B8X8: |
| 618 | + return ffi::WGPUExternalTextureFormat_Rgba; |
| 619 | + case gfx::SurfaceFormat::YUV420: |
| 620 | + return ffi::WGPUExternalTextureFormat_Yu12; |
| 621 | + case gfx::SurfaceFormat::NV12: |
| 622 | + return ffi::WGPUExternalTextureFormat_Nv12; |
| 623 | + default: |
| 624 | + MOZ_CRASH("Unexpected SurfaceFormat"); |
| 625 | + } |
| 626 | +} |
| 627 | + |
| 628 | +static ffi::WGPUExternalTextureTransferFunction MapTransferFunction( |
| 629 | + std::optional<color::PiecewiseGammaDesc> aTf) { |
| 630 | + if (aTf) { |
| 631 | + return ffi::WGPUExternalTextureTransferFunction{ |
| 632 | + .a = aTf->a, |
| 633 | + .b = aTf->b, |
| 634 | + .g = aTf->g, |
| 635 | + .k = aTf->k, |
| 636 | + }; |
| 637 | + } else { |
| 638 | + return ffi::WGPUExternalTextureTransferFunction{ |
| 639 | + .a = 1.0, |
| 640 | + .b = 1.0, |
| 641 | + .g = 1.0, |
| 642 | + .k = 1.0, |
| 643 | + }; |
| 644 | + } |
| 645 | +} |
| 646 | + |
| 647 | +ffi::WGPUExternalTextureDescriptorFromSource |
| 648 | +ExternalTextureSourceHost::GetExternalTextureDescriptor( |
| 649 | + ffi::WGPUPredefinedColorSpace aDestColorSpace) const { |
| 650 | + ffi::WGPUExternalTextureDescriptorFromSource desc; |
| 651 | + |
| 652 | + desc.planes = ffi::WGPUFfiSlice_TextureViewId{ |
| 653 | + .data = mViewIds.Elements(), |
| 654 | + .length = mViewIds.Length(), |
| 655 | + }; |
| 656 | + desc.width = static_cast<uint32_t>(mSize.width); |
| 657 | + desc.height = static_cast<uint32_t>(mSize.height); |
| 658 | + desc.format = MapFormat(mFormat); |
| 659 | + |
| 660 | + auto colorSpaceTransform = |
| 661 | + GetColorSpaceTransform(mColorSpace, aDestColorSpace); |
| 662 | + // Makes a generator for a color::mat that yields its components in |
| 663 | + // column-major order |
| 664 | + auto make_column_major_generator = [](auto mat) { |
| 665 | + return [i = 0, mat]() mutable { |
| 666 | + auto val = mat.at(i / mat.y_rows, i % mat.y_rows); |
| 667 | + i++; |
| 668 | + return val; |
| 669 | + }; |
| 670 | + }; |
| 671 | + std::generate( |
| 672 | + std::begin(desc.yuv_conversion_matrix), |
| 673 | + std::end(desc.yuv_conversion_matrix), |
| 674 | + make_column_major_generator(colorSpaceTransform.srcRgbTfFromSrc)); |
| 675 | + std::generate( |
| 676 | + std::begin(desc.gamut_conversion_matrix), |
| 677 | + std::end(desc.gamut_conversion_matrix), |
| 678 | + make_column_major_generator(colorSpaceTransform.dstRgbLinFromSrcRgbLin)); |
| 679 | + desc.src_transfer_function = MapTransferFunction(colorSpaceTransform.srcTf); |
| 680 | + desc.dst_transfer_function = MapTransferFunction(colorSpaceTransform.dstTf); |
| 681 | + std::copy(mSampleTransform.begin(), mSampleTransform.end(), |
| 682 | + desc.sample_transform); |
| 683 | + std::copy(mLoadTransform.begin(), mLoadTransform.end(), desc.load_transform); |
| 684 | + |
| 685 | + return desc; |
| 686 | +} |
| 687 | + |
449 | 688 | } // namespace mozilla::webgpu |
0 commit comments