Bug 1880926 - Check if system enables HDR on Windows r=gfx-reviewers,lsalzman

By using IDXGIOutput6, we could check if system enables HDR on Windows.

DeviceManagerDx::SystemHDREnabled() is expected to be called in GPU process.

Differential Revision: https://phabricator.services.mozilla.com/D202186
This commit is contained in:
sotaro 2024-02-20 02:58:29 +00:00
Родитель 0867c79a78
Коммит 6919c26e41
7 изменённых файлов: 148 добавлений и 0 удалений

Просмотреть файл

@ -571,6 +571,13 @@ mozilla::ipc::IPCResult GPUParent::RecvPreferenceUpdate(const Pref& aPref) {
return IPC_OK();
}
mozilla::ipc::IPCResult GPUParent::RecvScreenInformationChanged() {
#if defined(XP_WIN)
DeviceManagerDx::Get()->PostUpdateMonitorInfo();
#endif
return IPC_OK();
}
static void CopyFeatureChange(Feature aFeature, Maybe<FeatureFailure>* aOut) {
FeatureState& feature = gfxConfig::GetFeature(aFeature);
if (feature.DisabledByDefault() || feature.IsEnabled()) {

Просмотреть файл

@ -74,6 +74,7 @@ class GPUParent final : public PGPUParent {
Endpoint<PProfilerChild>&& aEndpoint);
mozilla::ipc::IPCResult RecvUpdateVar(const GfxVarUpdate& pref);
mozilla::ipc::IPCResult RecvPreferenceUpdate(const Pref& pref);
mozilla::ipc::IPCResult RecvScreenInformationChanged();
mozilla::ipc::IPCResult RecvNewContentCompositorManager(
Endpoint<PCompositorManagerParent>&& aEndpoint,
const ContentParentId& aChildId, uint32_t aNamespace);

Просмотреть файл

@ -136,6 +136,8 @@ GPUProcessManager::Observer::Observe(nsISupports* aSubject, const char* aTopic,
}
} else if (!strcmp(aTopic, "application-background")) {
mManager->mAppInForeground = false;
} else if (!strcmp(aTopic, "screen-information-changed")) {
mManager->ScreenInformationChanged();
}
return NS_OK;
}
@ -148,6 +150,7 @@ void GPUProcessManager::OnXPCOMShutdown() {
if (obsServ) {
obsServ->RemoveObserver(mObserver, "application-foreground");
obsServ->RemoveObserver(mObserver, "application-background");
obsServ->RemoveObserver(mObserver, "screen-information-changed");
}
mObserver = nullptr;
}
@ -172,6 +175,14 @@ void GPUProcessManager::OnPreferenceChange(const char16_t* aData) {
}
}
void GPUProcessManager::ScreenInformationChanged() {
#if defined(XP_WIN)
if (!!mGPUChild) {
mGPUChild->SendScreenInformationChanged();
}
#endif
}
void GPUProcessManager::ResetProcessStable() {
mTotalProcessAttempts++;
mProcessStable = false;
@ -207,6 +218,7 @@ bool GPUProcessManager::LaunchGPUProcess() {
if (obsServ) {
obsServ->AddObserver(mObserver, "application-foreground", false);
obsServ->AddObserver(mObserver, "application-background", false);
obsServ->AddObserver(mObserver, "screen-information-changed", false);
}
}

Просмотреть файл

@ -214,6 +214,7 @@ class GPUProcessManager final : public GPUProcessHost::Listener {
// Called from our xpcom-shutdown observer.
void OnXPCOMShutdown();
void OnPreferenceChange(const char16_t* aData);
void ScreenInformationChanged();
bool CreateContentCompositorManager(
base::ProcessId aOtherProcess, dom::ContentParentId aChildId,

Просмотреть файл

@ -79,6 +79,7 @@ parent:
async UpdateVar(GfxVarUpdate var);
async PreferenceUpdate(Pref pref);
async ScreenInformationChanged();
// Create a new content-process compositor bridge.
async NewContentCompositorManager(Endpoint<PCompositorManagerParent> endpoint, ContentParentId childId, uint32_t aNamespace);

Просмотреть файл

@ -206,6 +206,122 @@ bool DeviceManagerDx::GetOutputFromMonitor(HMONITOR monitor,
return false;
}
void DeviceManagerDx::PostUpdateMonitorInfo() {
MOZ_ASSERT(XRE_IsGPUProcess());
MOZ_ASSERT(NS_IsMainThread());
MutexAutoLock lock(mDeviceLock);
// Reduce frequency of UpdateMonitorInfo() call.
if (mUpdateMonitorInfoRunnable) {
return;
}
auto* holder = CompositorThreadHolder::GetSingleton();
if (!holder) {
return;
}
mUpdateMonitorInfoRunnable = NS_NewRunnableFunction(
"DeviceManagerDx::PostUpdateMonitorInfo::Runnable", []() -> void {
auto* dm = gfx::DeviceManagerDx::Get();
if (dm) {
dm->UpdateMonitorInfo();
}
});
const uint32_t kDelayMS = 100;
RefPtr<Runnable> runnable = mUpdateMonitorInfoRunnable;
holder->GetCompositorThread()->DelayedDispatch(runnable.forget(), kDelayMS);
}
void DeviceManagerDx::UpdateMonitorInfo() {
bool systemHdrEnabled = false;
for (const auto& desc : GetOutputDescs()) {
if (desc.ColorSpace == DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020) {
systemHdrEnabled = true;
}
}
{
MutexAutoLock lock(mDeviceLock);
mSystemHdrEnabled = Some(systemHdrEnabled);
mUpdateMonitorInfoRunnable = nullptr;
}
}
std::vector<DXGI_OUTPUT_DESC1> DeviceManagerDx::GetOutputDescs() {
HRESULT hr;
std::vector<DXGI_OUTPUT_DESC1> outputDescs;
RefPtr<IDXGIFactory1> dxgiFactory;
hr = ::CreateDXGIFactory1(__uuidof(IDXGIFactory1),
getter_AddRefs(dxgiFactory));
if (FAILED(hr)) {
gfxCriticalNoteOnce << "Failed to create DXGI factory: " << gfx::hexa(hr);
return outputDescs;
}
for (UINT adapterIndex = 0;; adapterIndex++) {
RefPtr<IDXGIAdapter> adapter;
hr = dxgiFactory->EnumAdapters(adapterIndex, getter_AddRefs(adapter));
if (hr == DXGI_ERROR_NOT_FOUND) {
break;
}
if (FAILED(hr)) {
MOZ_ASSERT_UNREACHABLE("unexpected to be called");
gfxCriticalNoteOnce << "Failed to enumerate DXGI adapter: "
<< gfx::hexa(hr);
break;
}
for (UINT outputIndex = 0;; ++outputIndex) {
RefPtr<IDXGIOutput> output;
hr = adapter->EnumOutputs(outputIndex, getter_AddRefs(output));
if (hr == DXGI_ERROR_NOT_FOUND) {
break;
}
if (FAILED(hr)) {
MOZ_ASSERT_UNREACHABLE("unexpected to be called");
gfxCriticalNoteOnce << "Failed to enumulate DXGI output: "
<< gfx::hexa(hr);
break;
}
RefPtr<IDXGIOutput6> output6;
hr = output->QueryInterface(__uuidof(IDXGIOutput6),
getter_AddRefs(output6));
if (FAILED(hr)) {
continue;
}
DXGI_OUTPUT_DESC1 desc;
if (FAILED(output6->GetDesc1(&desc))) {
MOZ_ASSERT_UNREACHABLE("unexpected to be called");
gfxCriticalNoteOnce << "Failed to get DXGI output descriptor";
continue;
}
outputDescs.push_back(std::move(desc));
}
}
return outputDescs;
}
bool DeviceManagerDx::SystemHDREnabled() {
{
MutexAutoLock lock(mDeviceLock);
if (mSystemHdrEnabled.isSome()) {
return mSystemHdrEnabled.ref();
}
}
UpdateMonitorInfo();
MutexAutoLock lock(mDeviceLock);
return mSystemHdrEnabled.ref();
}
void DeviceManagerDx::CheckHardwareStretchingSupport(HwStretchingSupport& aRv) {
RefPtr<IDXGIAdapter> adapter = GetDXGIAdapter();

Просмотреть файл

@ -6,6 +6,8 @@
#ifndef mozilla_gfx_thebes_DeviceManagerDx_h
#define mozilla_gfx_thebes_DeviceManagerDx_h
#include <vector>
#include "gfxPlatform.h"
#include "gfxTelemetry.h"
#include "gfxTypes.h"
@ -88,6 +90,9 @@ class DeviceManagerDx final {
// 'monitor'; returns false if not found or some error occurred.
bool GetOutputFromMonitor(HMONITOR monitor, RefPtr<IDXGIOutput>* aOutOutput);
void PostUpdateMonitorInfo();
bool SystemHDREnabled();
// Check if the current adapter supports hardware stretching
void CheckHardwareStretchingSupport(HwStretchingSupport& aRv);
@ -172,6 +177,9 @@ class DeviceManagerDx final {
bool GetAnyDeviceRemovedReason(DeviceResetReason* aOutReason)
MOZ_REQUIRES(mDeviceLock);
void UpdateMonitorInfo();
std::vector<DXGI_OUTPUT_DESC1> GetOutputDescs();
private:
static StaticAutoPtr<DeviceManagerDx> sInstance;
@ -198,6 +206,8 @@ class DeviceManagerDx final {
bool mCompositorDeviceSupportsVideo MOZ_GUARDED_BY(mDeviceLock);
Maybe<D3D11DeviceStatus> mDeviceStatus MOZ_GUARDED_BY(mDeviceLock);
Maybe<DeviceResetReason> mDeviceResetReason MOZ_GUARDED_BY(mDeviceLock);
RefPtr<Runnable> mUpdateMonitorInfoRunnable MOZ_GUARDED_BY(mDeviceLock);
Maybe<bool> mSystemHdrEnabled MOZ_GUARDED_BY(mDeviceLock);
nsModuleHandle mDirectDrawDLL;
RefPtr<IDirectDraw7> mDirectDraw;