зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1799258 - Do color-management on Windows+DComp via IDCompositionFilterEffects. r=sotaro
+ Add gfx.color_management.rec709_gamma_as_srgb:true. :'( In particular, rec709(16/255) -> srgb(31/255). Even though it's technically correct, it's practically-speaking incorrect, since that's not what Chrome does, nor what the web expected for years and years. In practice, basically everyone expects gamma to just be completely ignored. What people expect: * Pretend gamut is srgb(==rec709), but stretch this naively for the display. If you have a display-p3-gamut display, srgb:0.5 expects to be displayed as display:0.5, which will be display-p3:0.5 to the eyes. * Pretend all content gammas (TFs) are srgb(!=rec790), and then bitcast this naively for the display. E.g. rec709(16/255) should display the same as srgb(16/255), not srgb(31/255). (Note: display-p3 uses srgb gamma) But if your display has e.g. gamma=3.0, don't convert or compensate. This is a formalization of what you get when you spend decades ignoring color management, and people build things based on behavior-in-practice, not behavior-in-theory. Also: + gfx.color_management.native_srgb:true for Windows, so we don't use the display color profile, which no one else does. + Add rec2020_gamma_as_rec709, so we have a path towards maybe having rec2020 use its correct transfer function, rather than srgb (like rec709). Differential Revision: https://phabricator.services.mozilla.com/D161857
This commit is contained in:
Родитель
70f8fd53cc
Коммит
9e2d016bd4
|
@ -17,7 +17,7 @@ defaults pref(media.av1.enabled,true)
|
|||
fuzzy(16-51,5234-5622) fuzzy-if(swgl,32-38,1600-91746) fuzzy-if(useDrawSnapshot,16-16,11600-11600) fuzzy-if(OSX,16-73,5212-5622) == ../reftest_video.html?src=color_quads/720p.png.bt709.bt709.tv.yuv420p.av1.webm ../reftest_img.html?src=color_quads/720p.png
|
||||
fuzzy-if(winWidget&&swgl,0-20,0-5620) fuzzy-if(winWidget&&!swgl,0-1,0-78) fuzzy-if(Android,254-255,273680-273807) fuzzy-if(OSX,0-35,0-1947) fuzzy-if(OSX&&swgl,0-67,0-5451) fuzzy-if(appleSilicon,30-48,1760-187409) == ../reftest_video.html?src=color_quads/720p.png.bt709.bt709.tv.yuv420p.vp9.webm ../reftest_video.html?src=color_quads/720p.png.bt709.bt709.tv.yuv420p.av1.webm
|
||||
fuzzy-if(winWidget,0-1,0-78) == ../reftest_video.html?src=color_quads/720p.png.bt709.bt709.tv.yuv420p.av1.mp4 ../reftest_video.html?src=color_quads/720p.png.bt709.bt709.tv.yuv420p.av1.webm
|
||||
skip-if(winWidget&&isCoverageBuild) fuzzy(0-16,75-1861) fuzzy-if(Android,254-255,273680-273807) fuzzy-if(OSX,30-32,187326-187407) fuzzy-if(appleSilicon,30-48,1835-187409) == ../reftest_video.html?src=color_quads/720p.png.bt709.bt709.tv.yuv420p.h264.mp4 ../reftest_video.html?src=color_quads/720p.png.bt709.bt709.tv.yuv420p.av1.webm
|
||||
skip-if(winWidget&&isCoverageBuild) fuzzy(0-16,75-1941) fuzzy-if(Android,254-255,273680-273807) fuzzy-if(OSX,30-32,187326-187407) fuzzy-if(appleSilicon,30-48,1835-187409) == ../reftest_video.html?src=color_quads/720p.png.bt709.bt709.tv.yuv420p.h264.mp4 ../reftest_video.html?src=color_quads/720p.png.bt709.bt709.tv.yuv420p.av1.webm
|
||||
fuzzy-if(winWidget&&swgl,0-20,0-5620) fuzzy-if(winWidget&&!swgl,0-1,0-78) fuzzy-if(Android,254-255,273680-273807) fuzzy-if(OSX,0-35,0-1947) fuzzy-if(OSX&&swgl,0-67,0-5451) fuzzy-if(appleSilicon,30-48,1760-187409) == ../reftest_video.html?src=color_quads/720p.png.bt709.bt709.tv.yuv420p.vp9.mp4 ../reftest_video.html?src=color_quads/720p.png.bt709.bt709.tv.yuv420p.av1.webm
|
||||
|
||||
skip-if(Android) fuzzy(16-48,8107-8818) fuzzy-if(winWidget&&swgl,31-38,8240-184080) fuzzy-if(appleSilicon,33-38,8819-11705) fuzzy-if(useDrawSnapshot,20-20,187200-187200) == ../reftest_video.html?src=color_quads/720p.png.bt709.bt709.pc.yuv420p.av1.webm ../reftest_img.html?src=color_quads/720p.png
|
||||
|
|
|
@ -30,6 +30,10 @@
|
|||
#undef NTDDI_VERSION
|
||||
#define NTDDI_VERSION NTDDI_WINBLUE
|
||||
|
||||
// We also need this, or dcomp.h won't give us e.g. IDCompositionDevice3:
|
||||
#undef _WIN32_WINNT_WINTHRESHOLD
|
||||
#define _WIN32_WINNT_WINTHRESHOLD _WIN32_WINNT
|
||||
|
||||
#include <d3d11.h>
|
||||
#include <dcomp.h>
|
||||
#include <ddraw.h>
|
||||
|
@ -50,6 +54,7 @@ decltype(D3D11CreateDevice)* sD3D11CreateDeviceFn = nullptr;
|
|||
|
||||
// It should only be used within CreateDirectCompositionDevice.
|
||||
decltype(DCompositionCreateDevice2)* sDcompCreateDevice2Fn = nullptr;
|
||||
decltype(DCompositionCreateDevice3)* sDcompCreateDevice3Fn = nullptr;
|
||||
|
||||
// It should only be used within CreateDCompSurfaceHandle
|
||||
decltype(DCompositionCreateSurfaceHandle)* sDcompCreateSurfaceHandleFn =
|
||||
|
@ -117,7 +122,7 @@ bool DeviceManagerDx::LoadDcomp() {
|
|||
MOZ_ASSERT(gfxVars::UseWebRenderDCompWin());
|
||||
|
||||
if (sDcompCreateDevice2Fn) {
|
||||
return true;
|
||||
return true; // Already loaded.
|
||||
}
|
||||
|
||||
nsModuleHandle module(LoadLibrarySystem32(L"dcomp.dll"));
|
||||
|
@ -127,6 +132,8 @@ bool DeviceManagerDx::LoadDcomp() {
|
|||
|
||||
sDcompCreateDevice2Fn = (decltype(DCompositionCreateDevice2)*)GetProcAddress(
|
||||
module, "DCompositionCreateDevice2");
|
||||
sDcompCreateDevice3Fn = (decltype(DCompositionCreateDevice3)*)GetProcAddress(
|
||||
module, "DCompositionCreateDevice3");
|
||||
if (!sDcompCreateDevice2Fn) {
|
||||
return false;
|
||||
}
|
||||
|
@ -135,9 +142,6 @@ bool DeviceManagerDx::LoadDcomp() {
|
|||
sDcompCreateSurfaceHandleFn =
|
||||
(decltype(DCompositionCreateSurfaceHandle)*)::GetProcAddress(
|
||||
module, "DCompositionCreateSurfaceHandle");
|
||||
if (!sDcompCreateDevice2Fn) {
|
||||
return false;
|
||||
}
|
||||
|
||||
mDcompModule.steal(module);
|
||||
return true;
|
||||
|
@ -448,10 +452,16 @@ void DeviceManagerDx::CreateDirectCompositionDeviceLocked() {
|
|||
HRESULT hr;
|
||||
RefPtr<IDCompositionDesktopDevice> desktopDevice;
|
||||
MOZ_SEH_TRY {
|
||||
hr = sDcompCreateDevice2Fn(
|
||||
hr = sDcompCreateDevice3Fn(
|
||||
dxgiDevice.get(),
|
||||
IID_PPV_ARGS(
|
||||
(IDCompositionDesktopDevice**)getter_AddRefs(desktopDevice)));
|
||||
if (!desktopDevice) {
|
||||
hr = sDcompCreateDevice2Fn(
|
||||
dxgiDevice.get(),
|
||||
IID_PPV_ARGS(
|
||||
(IDCompositionDesktopDevice**)getter_AddRefs(desktopDevice)));
|
||||
}
|
||||
}
|
||||
MOZ_SEH_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { return; }
|
||||
|
||||
|
|
|
@ -2028,15 +2028,10 @@ DeviceColor gfxPlatform::TransformPixel(const sRGBColor& in,
|
|||
return DeviceColor(in.r, in.g, in.b, in.a);
|
||||
}
|
||||
|
||||
nsTArray<uint8_t> gfxPlatform::GetPlatformCMSOutputProfileData() {
|
||||
return GetPrefCMSOutputProfileData();
|
||||
}
|
||||
|
||||
nsTArray<uint8_t> gfxPlatform::GetPrefCMSOutputProfileData() {
|
||||
nsAutoCString fname;
|
||||
Preferences::GetCString("gfx.color_management.display_profile", fname);
|
||||
|
||||
if (fname.IsEmpty()) {
|
||||
const auto mirror = StaticPrefs::gfx_color_management_display_profile();
|
||||
const auto fname = *mirror;
|
||||
if (fname == "") {
|
||||
return nsTArray<uint8_t>();
|
||||
}
|
||||
|
||||
|
|
|
@ -751,7 +751,9 @@ class gfxPlatform : public mozilla::layers::MemoryPressureListener {
|
|||
* Returns a buffer containing the CMS output profile data. The way this
|
||||
* is obtained is platform-specific.
|
||||
*/
|
||||
virtual nsTArray<uint8_t> GetPlatformCMSOutputProfileData();
|
||||
virtual nsTArray<uint8_t> GetPlatformCMSOutputProfileData() {
|
||||
return GetPrefCMSOutputProfileData();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return information on how child processes should initialize graphics
|
||||
|
@ -863,13 +865,15 @@ class gfxPlatform : public mozilla::layers::MemoryPressureListener {
|
|||
virtual void ImportContentDeviceData(
|
||||
const mozilla::gfx::ContentDeviceData& aData);
|
||||
|
||||
public:
|
||||
/**
|
||||
* Returns the contents of the file pointed to by the
|
||||
* gfx.color_management.display_profile pref, if set.
|
||||
* Returns an empty array if not set, or if an error occurs
|
||||
*/
|
||||
nsTArray<uint8_t> GetPrefCMSOutputProfileData();
|
||||
static nsTArray<uint8_t> GetPrefCMSOutputProfileData();
|
||||
|
||||
protected:
|
||||
/**
|
||||
* If inside a child process and currently being initialized by the
|
||||
* SetXPCOMProcessAttributes message, this can be used by subclasses to
|
||||
|
|
|
@ -1036,16 +1036,21 @@ nsTArray<uint8_t> gfxWindowsPlatform::GetPlatformCMSOutputProfileData() {
|
|||
return result;
|
||||
}
|
||||
|
||||
if (!mCachedOutputColorProfile.IsEmpty()) {
|
||||
return mCachedOutputColorProfile.Clone();
|
||||
}
|
||||
return GetPlatformCMSOutputProfileData_Impl();
|
||||
}
|
||||
|
||||
mCachedOutputColorProfile = [&] {
|
||||
nsTArray<uint8_t> prefProfileData = GetPrefCMSOutputProfileData();
|
||||
nsTArray<uint8_t> gfxWindowsPlatform::GetPlatformCMSOutputProfileData_Impl() {
|
||||
static nsTArray<uint8_t> sCached = [&] {
|
||||
// Check override pref first:
|
||||
nsTArray<uint8_t> prefProfileData =
|
||||
gfxPlatform::GetPrefCMSOutputProfileData();
|
||||
if (!prefProfileData.IsEmpty()) {
|
||||
return prefProfileData;
|
||||
}
|
||||
|
||||
// -
|
||||
// Otherwise, create a dummy DC and pull from that.
|
||||
|
||||
HDC dc = ::GetDC(nullptr);
|
||||
if (!dc) {
|
||||
return nsTArray<uint8_t>();
|
||||
|
@ -1078,7 +1083,7 @@ nsTArray<uint8_t> gfxWindowsPlatform::GetPlatformCMSOutputProfileData() {
|
|||
return result;
|
||||
}();
|
||||
|
||||
return mCachedOutputColorProfile.Clone();
|
||||
return sCached.Clone();
|
||||
}
|
||||
|
||||
void gfxWindowsPlatform::GetDLLVersion(char16ptr_t aDLLPath,
|
||||
|
|
|
@ -200,7 +200,13 @@ class gfxWindowsPlatform final : public gfxPlatform {
|
|||
|
||||
protected:
|
||||
bool AccelerateLayersByDefault() override { return true; }
|
||||
|
||||
nsTArray<uint8_t> GetPlatformCMSOutputProfileData() override;
|
||||
|
||||
public:
|
||||
static nsTArray<uint8_t> GetPlatformCMSOutputProfileData_Impl();
|
||||
|
||||
protected:
|
||||
void GetPlatformDisplayInfo(mozilla::widget::InfoObject& aObj) override;
|
||||
|
||||
void ImportGPUDeviceData(const mozilla::gfx::GPUDeviceData& aData) override;
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
#include "DCLayerTree.h"
|
||||
|
||||
#include "gfxWindowsPlatform.h"
|
||||
#include "GLContext.h"
|
||||
#include "GLContextEGL.h"
|
||||
#include "mozilla/gfx/DeviceManagerDx.h"
|
||||
|
@ -28,6 +29,10 @@
|
|||
#undef NTDDI_VERSION
|
||||
#define NTDDI_VERSION NTDDI_WINBLUE
|
||||
|
||||
// We also need this, or dcomp.h won't give us e.g. IDCompositionFilterEffect:
|
||||
#undef _WIN32_WINNT_WINTHRESHOLD
|
||||
#define _WIN32_WINNT_WINTHRESHOLD _WIN32_WINNT
|
||||
|
||||
#include <d3d11.h>
|
||||
#include <d3d11_1.h>
|
||||
#include <dcomp.h>
|
||||
|
@ -567,6 +572,16 @@ void DCExternalSurfaceWrapper::AttachExternalImage(
|
|||
}
|
||||
}
|
||||
|
||||
template <class ToT>
|
||||
struct QI {
|
||||
template <class FromT>
|
||||
[[nodiscard]] static inline RefPtr<ToT> From(FromT* const from) {
|
||||
RefPtr<ToT> to;
|
||||
(void)from->QueryInterface(static_cast<ToT**>(getter_AddRefs(to)));
|
||||
return to;
|
||||
}
|
||||
};
|
||||
|
||||
DCSurface* DCExternalSurfaceWrapper::EnsureSurfaceForExternalImage(
|
||||
wr::ExternalImageId aExternalImage) {
|
||||
if (mSurface) {
|
||||
|
@ -591,14 +606,117 @@ DCSurface* DCExternalSurfaceWrapper::EnsureSurfaceForExternalImage(
|
|||
mSurface = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
if (mSurface) {
|
||||
// Add surface's visual which will contain video data to our root visual.
|
||||
mVisual->AddVisual(mSurface->GetVisual(), TRUE, nullptr);
|
||||
} else {
|
||||
if (!mSurface) {
|
||||
gfxCriticalNote << "Failed to create a surface for external image: "
|
||||
<< gfx::hexa(texture);
|
||||
return nullptr;
|
||||
}
|
||||
const auto textureSwgl = texture->AsRenderTextureHostSWGL();
|
||||
MOZ_ASSERT(textureSwgl); // Covered above.
|
||||
|
||||
// Add surface's visual which will contain video data to our root visual.
|
||||
const auto surfaceVisual = mSurface->GetVisual();
|
||||
mVisual->AddVisual(surfaceVisual, true, nullptr);
|
||||
|
||||
// -
|
||||
// Apply color management.
|
||||
|
||||
[&]() {
|
||||
const auto cmsMode = GfxColorManagementMode();
|
||||
if (cmsMode == CMSMode::Off) return;
|
||||
|
||||
const auto dcomp = mDCLayerTree->GetCompositionDevice();
|
||||
const auto dcomp3 = QI<IDCompositionDevice3>::From(dcomp);
|
||||
if (!dcomp3) {
|
||||
NS_WARNING(
|
||||
"No IDCompositionDevice3, cannot use dcomp for color management.");
|
||||
return;
|
||||
}
|
||||
|
||||
// -
|
||||
|
||||
const auto cspace = [&]() {
|
||||
const auto rangedCspace = textureSwgl->GetYUVColorSpace();
|
||||
const auto info = FromYUVRangedColorSpace(rangedCspace);
|
||||
auto ret = ToColorSpace2(info.space);
|
||||
if (ret == gfx::ColorSpace2::Display && cmsMode == CMSMode::All) {
|
||||
ret = gfx::ColorSpace2::SRGB;
|
||||
}
|
||||
return ret;
|
||||
}();
|
||||
|
||||
const bool rec709GammaAsSrgb =
|
||||
StaticPrefs::gfx_color_management_rec709_gamma_as_srgb();
|
||||
const bool rec2020GammaAsRec709 =
|
||||
StaticPrefs::gfx_color_management_rec2020_gamma_as_rec709();
|
||||
|
||||
auto cspaceDesc = color::ColorspaceDesc{};
|
||||
switch (cspace) {
|
||||
case gfx::ColorSpace2::Display:
|
||||
return; // No color management needed!
|
||||
case gfx::ColorSpace2::SRGB:
|
||||
cspaceDesc.chrom = color::Chromaticities::Srgb();
|
||||
cspaceDesc.tf = color::PiecewiseGammaDesc::Srgb();
|
||||
break;
|
||||
|
||||
case gfx::ColorSpace2::DISPLAY_P3:
|
||||
cspaceDesc.chrom = color::Chromaticities::DisplayP3();
|
||||
cspaceDesc.tf = color::PiecewiseGammaDesc::DisplayP3();
|
||||
break;
|
||||
|
||||
case gfx::ColorSpace2::BT601_525:
|
||||
cspaceDesc.chrom = color::Chromaticities::Rec601_525_Ntsc();
|
||||
if (rec709GammaAsSrgb) {
|
||||
cspaceDesc.tf = color::PiecewiseGammaDesc::Srgb();
|
||||
} else {
|
||||
cspaceDesc.tf = color::PiecewiseGammaDesc::Rec709();
|
||||
}
|
||||
break;
|
||||
|
||||
case gfx::ColorSpace2::BT709:
|
||||
cspaceDesc.chrom = color::Chromaticities::Rec709();
|
||||
if (rec709GammaAsSrgb) {
|
||||
cspaceDesc.tf = color::PiecewiseGammaDesc::Srgb();
|
||||
} else {
|
||||
cspaceDesc.tf = color::PiecewiseGammaDesc::Rec709();
|
||||
}
|
||||
break;
|
||||
|
||||
case gfx::ColorSpace2::BT2020:
|
||||
cspaceDesc.chrom = color::Chromaticities::Rec2020();
|
||||
if (rec2020GammaAsRec709 && rec709GammaAsSrgb) {
|
||||
cspaceDesc.tf = color::PiecewiseGammaDesc::Srgb();
|
||||
} else if (rec2020GammaAsRec709) {
|
||||
cspaceDesc.tf = color::PiecewiseGammaDesc::Rec709();
|
||||
} else {
|
||||
// Just Rec709 with slightly more precision.
|
||||
cspaceDesc.tf = color::PiecewiseGammaDesc::Rec2020_12bit();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
const auto cprofileIn = color::ColorProfileDesc::From(cspaceDesc);
|
||||
auto cprofileOut = mDCLayerTree->OutputColorProfile();
|
||||
bool pretendSrgb = StaticPrefs::gfx_color_management_native_srgb();
|
||||
if (pretendSrgb) {
|
||||
cprofileOut = color::ColorProfileDesc::From({
|
||||
color::Chromaticities::Srgb(),
|
||||
color::PiecewiseGammaDesc::Srgb(),
|
||||
});
|
||||
}
|
||||
const auto conversion = color::ColorProfileConversionDesc::From({
|
||||
.src = cprofileIn,
|
||||
.dst = cprofileOut,
|
||||
});
|
||||
|
||||
// -
|
||||
|
||||
auto chain = ColorManagementChain::From(*dcomp3, conversion);
|
||||
mCManageChain = Some(chain);
|
||||
|
||||
surfaceVisual->SetEffect(mCManageChain->last.get());
|
||||
}();
|
||||
|
||||
return mSurface.get();
|
||||
}
|
||||
|
||||
|
@ -1591,6 +1709,114 @@ void DCLayerTree::DestroyEGLSurface() {
|
|||
}
|
||||
}
|
||||
|
||||
// -
|
||||
|
||||
color::ColorProfileDesc DCLayerTree::QueryOutputColorProfile() {
|
||||
// GPU process can't simply init gfxPlatform, (and we don't need most of it)
|
||||
// but we do need gfxPlatform::GetCMSOutputProfile().
|
||||
// So we steal what we need through the window:
|
||||
const auto outputProfileData =
|
||||
gfxWindowsPlatform::GetPlatformCMSOutputProfileData_Impl();
|
||||
|
||||
const auto qcmsProfile = qcms_profile_from_memory(
|
||||
outputProfileData.Elements(), outputProfileData.Length());
|
||||
MOZ_ASSERT(qcmsProfile);
|
||||
const auto release =
|
||||
MakeScopeExit([&]() { qcms_profile_release(qcmsProfile); });
|
||||
|
||||
const auto ret = color::ColorProfileDesc::From(*qcmsProfile);
|
||||
bool print = gfxEnv::MOZ_GL_SPEW();
|
||||
if (print) {
|
||||
const auto gammaGuess = color::GuessGamma(ret.linearFromTf.r);
|
||||
printf_stderr(
|
||||
"Display profile:\n"
|
||||
" Approx Gamma: %f\n"
|
||||
" XYZ-D65 Red : %f, %f, %f\n"
|
||||
" XYZ-D65 Green: %f, %f, %f\n"
|
||||
" XYZ-D65 Blue : %f, %f, %f\n",
|
||||
gammaGuess, ret.xyzd65FromLinearRgb.at(0, 0),
|
||||
ret.xyzd65FromLinearRgb.at(0, 1), ret.xyzd65FromLinearRgb.at(0, 2),
|
||||
|
||||
ret.xyzd65FromLinearRgb.at(1, 0), ret.xyzd65FromLinearRgb.at(1, 1),
|
||||
ret.xyzd65FromLinearRgb.at(1, 2),
|
||||
|
||||
ret.xyzd65FromLinearRgb.at(2, 0), ret.xyzd65FromLinearRgb.at(2, 1),
|
||||
ret.xyzd65FromLinearRgb.at(2, 2));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
inline D2D1_MATRIX_5X4_F to_D2D1_MATRIX_5X4_F(const color::mat4& m) {
|
||||
return D2D1_MATRIX_5X4_F{{{
|
||||
m.rows[0][0],
|
||||
m.rows[1][0],
|
||||
m.rows[2][0],
|
||||
m.rows[3][0],
|
||||
m.rows[0][1],
|
||||
m.rows[1][1],
|
||||
m.rows[2][1],
|
||||
m.rows[3][1],
|
||||
m.rows[0][2],
|
||||
m.rows[1][2],
|
||||
m.rows[2][2],
|
||||
m.rows[3][2],
|
||||
m.rows[0][3],
|
||||
m.rows[1][3],
|
||||
m.rows[2][3],
|
||||
m.rows[3][3],
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
}}};
|
||||
}
|
||||
|
||||
ColorManagementChain ColorManagementChain::From(
|
||||
IDCompositionDevice3& dcomp,
|
||||
const color::ColorProfileConversionDesc& conv) {
|
||||
auto ret = ColorManagementChain{};
|
||||
|
||||
const auto Append = [&](const RefPtr<IDCompositionFilterEffect>& afterLast) {
|
||||
if (ret.last) {
|
||||
afterLast->SetInput(0, ret.last, 0);
|
||||
}
|
||||
ret.last = afterLast;
|
||||
};
|
||||
|
||||
const auto MaybeAppendColorMatrix = [&](const color::mat4& m) {
|
||||
RefPtr<IDCompositionColorMatrixEffect> e;
|
||||
if (approx(m, color::mat4::Identity())) return e;
|
||||
dcomp.CreateColorMatrixEffect(getter_AddRefs(e));
|
||||
MOZ_ASSERT(e);
|
||||
if (!e) return e;
|
||||
e->SetMatrix(to_D2D1_MATRIX_5X4_F(m));
|
||||
Append(e);
|
||||
return e;
|
||||
};
|
||||
const auto MaybeAppendTableTransfer = [&](const color::RgbTransferTables& t) {
|
||||
RefPtr<IDCompositionTableTransferEffect> e;
|
||||
if (!t.r.size() && !t.g.size() && !t.b.size()) return e;
|
||||
dcomp.CreateTableTransferEffect(getter_AddRefs(e));
|
||||
MOZ_ASSERT(e);
|
||||
if (!e) return e;
|
||||
e->SetRedTable(t.r.data(), t.r.size());
|
||||
e->SetGreenTable(t.g.data(), t.g.size());
|
||||
e->SetBlueTable(t.b.data(), t.b.size());
|
||||
Append(e);
|
||||
return e;
|
||||
};
|
||||
|
||||
ret.srcRgbFromSrcYuv = MaybeAppendColorMatrix(conv.srcRgbFromSrcYuv);
|
||||
ret.srcLinearFromSrcTf = MaybeAppendTableTransfer(conv.srcLinearFromSrcTf);
|
||||
ret.dstLinearFromSrcLinear =
|
||||
MaybeAppendColorMatrix(color::mat4(conv.dstLinearFromSrcLinear));
|
||||
ret.dstTfFromDstLinear = MaybeAppendTableTransfer(conv.dstTfFromDstLinear);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ColorManagementChain::~ColorManagementChain() = default;
|
||||
|
||||
} // namespace wr
|
||||
} // namespace mozilla
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include <vector>
|
||||
#include <windows.h>
|
||||
|
||||
#include "Colorspaces.h"
|
||||
#include "GLTypes.h"
|
||||
#include "mozilla/HashFunctions.h"
|
||||
#include "mozilla/layers/OverlayInfo.h"
|
||||
|
@ -27,7 +28,11 @@ struct ID3D11VideoContext;
|
|||
struct ID3D11VideoProcessor;
|
||||
struct ID3D11VideoProcessorEnumerator;
|
||||
struct ID3D11VideoProcessorOutputView;
|
||||
struct IDCompositionColorMatrixEffect;
|
||||
struct IDCompositionFilterEffect;
|
||||
struct IDCompositionTableTransferEffect;
|
||||
struct IDCompositionDevice2;
|
||||
struct IDCompositionDevice3;
|
||||
struct IDCompositionSurface;
|
||||
struct IDCompositionTarget;
|
||||
struct IDCompositionVisual2;
|
||||
|
@ -66,6 +71,23 @@ struct GpuOverlayInfo {
|
|||
UINT mRgb10a2OverlaySupportFlags = 0;
|
||||
};
|
||||
|
||||
// -
|
||||
|
||||
struct ColorManagementChain {
|
||||
RefPtr<IDCompositionColorMatrixEffect> srcRgbFromSrcYuv;
|
||||
RefPtr<IDCompositionTableTransferEffect> srcLinearFromSrcTf;
|
||||
RefPtr<IDCompositionColorMatrixEffect> dstLinearFromSrcLinear;
|
||||
RefPtr<IDCompositionTableTransferEffect> dstTfFromDstLinear;
|
||||
RefPtr<IDCompositionFilterEffect> last;
|
||||
|
||||
static ColorManagementChain From(IDCompositionDevice3& dcomp,
|
||||
const color::ColorProfileConversionDesc&);
|
||||
|
||||
~ColorManagementChain();
|
||||
};
|
||||
|
||||
// -
|
||||
|
||||
/**
|
||||
* DCLayerTree manages direct composition layers.
|
||||
* It does not manage gecko's layers::Layer.
|
||||
|
@ -210,6 +232,19 @@ class DCLayerTree {
|
|||
|
||||
bool mPendingCommit;
|
||||
|
||||
static color::ColorProfileDesc QueryOutputColorProfile();
|
||||
|
||||
mutable Maybe<color::ColorProfileDesc> mOutputColorProfile;
|
||||
|
||||
public:
|
||||
const color::ColorProfileDesc& OutputColorProfile() const {
|
||||
if (!mOutputColorProfile) {
|
||||
mOutputColorProfile = Some(QueryOutputColorProfile());
|
||||
}
|
||||
return *mOutputColorProfile;
|
||||
}
|
||||
|
||||
protected:
|
||||
static UniquePtr<GpuOverlayInfo> sGpuOverlayInfo;
|
||||
};
|
||||
|
||||
|
@ -322,6 +357,7 @@ class DCExternalSurfaceWrapper : public DCSurface {
|
|||
|
||||
UniquePtr<DCSurface> mSurface;
|
||||
const bool mIsOpaque;
|
||||
Maybe<ColorManagementChain> mCManageChain;
|
||||
};
|
||||
|
||||
class DCSurfaceVideo : public DCSurface {
|
||||
|
|
|
@ -5690,6 +5690,11 @@
|
|||
#endif
|
||||
mirror: always
|
||||
|
||||
- name: gfx.color_management.display_profile
|
||||
type: DataMutexString
|
||||
value: ""
|
||||
mirror: always # But be warned: We cache the result.
|
||||
|
||||
- name: gfx.color_management.force_srgb
|
||||
type: RelaxedAtomicBool
|
||||
value: false
|
||||
|
@ -5697,7 +5702,7 @@
|
|||
|
||||
- name: gfx.color_management.native_srgb
|
||||
type: RelaxedAtomicBool
|
||||
#if defined(XP_MACOSX)
|
||||
#if defined(XP_MACOSX) || defined(XP_WIN)
|
||||
value: true
|
||||
#else
|
||||
value: false
|
||||
|
@ -5722,6 +5727,16 @@
|
|||
value: 0
|
||||
mirror: always
|
||||
|
||||
- name: gfx.color_management.rec709_gamma_as_srgb
|
||||
type: RelaxedAtomicBool
|
||||
value: true # Tragic backwards compat.
|
||||
mirror: always
|
||||
|
||||
- name: gfx.color_management.rec2020_gamma_as_rec709
|
||||
type: RelaxedAtomicBool
|
||||
value: true # Match naive behavior, but hopefully we can stop soon!
|
||||
mirror: always
|
||||
|
||||
- name: gfx.compositor.clearstate
|
||||
type: RelaxedAtomicBool
|
||||
value: false
|
||||
|
|
|
@ -454,8 +454,6 @@ pref("formhelper.autozoom.force-disable.test-only", false);
|
|||
pref("gfx.hidpi.enabled", 2);
|
||||
#endif
|
||||
|
||||
pref("gfx.color_management.display_profile", "");
|
||||
|
||||
pref("gfx.downloadable_fonts.enabled", true);
|
||||
pref("gfx.downloadable_fonts.fallback_delay", 3000);
|
||||
pref("gfx.downloadable_fonts.fallback_delay_short", 100);
|
||||
|
|
Загрузка…
Ссылка в новой задаче