mirror of
https://github.com/doitsujin/dxvk.git
synced 2024-11-30 04:24:11 +01:00
[dxgi] Implement gamma control methods for DxgiOutput
This commit is contained in:
parent
ad7f0971cf
commit
dd3f4c89ac
@ -6,6 +6,7 @@
|
||||
|
||||
#include "dxgi_adapter.h"
|
||||
#include "dxgi_output.h"
|
||||
#include "dxgi_swapchain.h"
|
||||
|
||||
#include "../dxvk/dxvk_format.h"
|
||||
|
||||
@ -229,20 +230,32 @@ namespace dxvk {
|
||||
|
||||
|
||||
HRESULT STDMETHODCALLTYPE DxgiOutput::GetFrameStatistics(DXGI_FRAME_STATISTICS *pStats) {
|
||||
Logger::err("DxgiOutput::GetFrameStatistics: Not implemented");
|
||||
return E_NOTIMPL;
|
||||
Com<DxgiSwapChain> swapChain = GetFullscreenSwapChain();
|
||||
|
||||
return swapChain != nullptr
|
||||
? swapChain->GetFrameStatistics(pStats)
|
||||
: DXGI_ERROR_NOT_CURRENTLY_AVAILABLE;
|
||||
}
|
||||
|
||||
|
||||
HRESULT STDMETHODCALLTYPE DxgiOutput::GetGammaControl(DXGI_GAMMA_CONTROL *pArray) {
|
||||
Logger::err("DxgiOutput::GetGammaControl: Not implemented");
|
||||
return E_NOTIMPL;
|
||||
Com<DxgiSwapChain> swapChain = GetFullscreenSwapChain();
|
||||
|
||||
return swapChain != nullptr
|
||||
? swapChain->GetGammaControl(pArray)
|
||||
: DXGI_ERROR_NOT_CURRENTLY_AVAILABLE;
|
||||
}
|
||||
|
||||
|
||||
HRESULT STDMETHODCALLTYPE DxgiOutput::GetGammaControlCapabilities(DXGI_GAMMA_CONTROL_CAPABILITIES *pGammaCaps) {
|
||||
Logger::err("DxgiOutput::GetGammaControlCapabilities: Not implemented");
|
||||
return E_NOTIMPL;
|
||||
pGammaCaps->ScaleAndOffsetSupported = TRUE;
|
||||
pGammaCaps->MaxConvertedValue = 1.0f;
|
||||
pGammaCaps->MinConvertedValue = 0.0f;
|
||||
pGammaCaps->NumGammaControlPoints = DxgiPresenterGammaRamp::CpCount;
|
||||
|
||||
for (uint32_t i = 0; i < pGammaCaps->NumGammaControlPoints; i++)
|
||||
pGammaCaps->ControlPointPositions[i] = DxgiPresenterGammaRamp::cpLocation(i);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
@ -258,8 +271,12 @@ namespace dxvk {
|
||||
|
||||
|
||||
HRESULT STDMETHODCALLTYPE DxgiOutput::SetGammaControl(const DXGI_GAMMA_CONTROL *pArray) {
|
||||
Logger::err("DxgiOutput::SetGammaControl: Not implemented");
|
||||
return E_NOTIMPL;
|
||||
Com<DxgiSwapChain> swapChain = GetFullscreenSwapChain();
|
||||
|
||||
Logger::err(str::format("DxgiOutput::SetGammaControl ", swapChain.ptr()));
|
||||
return swapChain != nullptr
|
||||
? swapChain->SetGammaControl(pArray)
|
||||
: DXGI_ERROR_NOT_CURRENTLY_AVAILABLE;
|
||||
}
|
||||
|
||||
|
||||
@ -277,6 +294,23 @@ namespace dxvk {
|
||||
}
|
||||
|
||||
|
||||
BOOL DxgiOutput::SetSwapChain(DxgiSwapChain* pExpected, DxgiSwapChain* pDesired) {
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
|
||||
if (m_fullscreenSwapChain == pExpected) {
|
||||
Logger::err(str::format("SetSwapChain: ", pDesired));
|
||||
m_fullscreenSwapChain = pDesired;
|
||||
return TRUE;
|
||||
} return FALSE;
|
||||
}
|
||||
|
||||
|
||||
Com<DxgiSwapChain> DxgiOutput::GetFullscreenSwapChain() {
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
return Com<DxgiSwapChain>(m_fullscreenSwapChain);
|
||||
}
|
||||
|
||||
|
||||
uint32_t DxgiOutput::GetFormatBpp(DXGI_FORMAT Format) const {
|
||||
DxgiFormatInfo formatInfo = m_adapter->LookupFormat(Format, DxgiFormatMode::Any);
|
||||
return imageFormatInfo(formatInfo.format)->elementSize * 8;
|
||||
|
@ -1,10 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include <mutex>
|
||||
|
||||
#include "dxgi_object.h"
|
||||
|
||||
namespace dxvk {
|
||||
|
||||
class DxgiAdapter;
|
||||
class DxgiSwapChain;
|
||||
|
||||
class DxgiOutput : public DxgiObject<IDXGIOutput> {
|
||||
|
||||
@ -64,11 +67,20 @@ namespace dxvk {
|
||||
|
||||
HRESULT STDMETHODCALLTYPE WaitForVBlank() final;
|
||||
|
||||
BOOL SetSwapChain(
|
||||
DxgiSwapChain* pExpected,
|
||||
DxgiSwapChain* pDesired);
|
||||
|
||||
private:
|
||||
|
||||
Com<DxgiAdapter> m_adapter = nullptr;
|
||||
DxgiAdapter* m_adapter = nullptr;
|
||||
HMONITOR m_monitor = nullptr;
|
||||
|
||||
std::mutex m_mutex;
|
||||
DxgiSwapChain* m_fullscreenSwapChain = nullptr;
|
||||
|
||||
Com<DxgiSwapChain> GetFullscreenSwapChain();
|
||||
|
||||
uint32_t GetFormatBpp(DXGI_FORMAT Format) const;
|
||||
|
||||
};
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include "dxgi_device.h"
|
||||
#include "dxgi_factory.h"
|
||||
#include "dxgi_output.h"
|
||||
#include "dxgi_swapchain.h"
|
||||
|
||||
namespace dxvk {
|
||||
@ -52,13 +53,14 @@ namespace dxvk {
|
||||
if (FAILED(CreatePresenter()) || FAILED(CreateBackBuffer()))
|
||||
throw DxvkError("DxgiSwapChain: Failed to create presenter or back buffer");
|
||||
|
||||
if (FAILED(SetDefaultGammaRamp()))
|
||||
if (FAILED(SetDefaultGammaControl()))
|
||||
throw DxvkError("DxgiSwapChain: Failed to set up gamma ramp");
|
||||
}
|
||||
|
||||
|
||||
DxgiSwapChain::~DxgiSwapChain() {
|
||||
|
||||
if (m_output != nullptr)
|
||||
m_output->SetSwapChain(this, nullptr);
|
||||
}
|
||||
|
||||
|
||||
@ -268,7 +270,52 @@ namespace dxvk {
|
||||
}
|
||||
|
||||
|
||||
HRESULT DxgiSwapChain::SetDefaultGammaRamp() {
|
||||
HRESULT DxgiSwapChain::GetGammaControl(DXGI_GAMMA_CONTROL* pGammaControl) {
|
||||
std::lock_guard<std::recursive_mutex> lock(m_mutex);
|
||||
|
||||
pGammaControl->Scale = {
|
||||
m_gammaControl.in_factor[0],
|
||||
m_gammaControl.in_factor[1],
|
||||
m_gammaControl.in_factor[2] };
|
||||
|
||||
pGammaControl->Offset = {
|
||||
m_gammaControl.in_offset[0],
|
||||
m_gammaControl.in_offset[1],
|
||||
m_gammaControl.in_offset[2] };
|
||||
|
||||
for (uint32_t i = 0; i < DxgiPresenterGammaRamp::CpCount; i++) {
|
||||
pGammaControl->GammaCurve[i] = {
|
||||
m_gammaControl.cp_values[4 * i + 0],
|
||||
m_gammaControl.cp_values[4 * i + 1],
|
||||
m_gammaControl.cp_values[4 * i + 2] };
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
HRESULT DxgiSwapChain::SetGammaControl(const DXGI_GAMMA_CONTROL* pGammaControl) {
|
||||
std::lock_guard<std::recursive_mutex> lock(m_mutex);
|
||||
m_gammaControl.in_factor[0] = pGammaControl->Scale.Red;
|
||||
m_gammaControl.in_factor[1] = pGammaControl->Scale.Green;
|
||||
m_gammaControl.in_factor[2] = pGammaControl->Scale.Blue;
|
||||
|
||||
m_gammaControl.in_offset[0] = pGammaControl->Offset.Red;
|
||||
m_gammaControl.in_offset[1] = pGammaControl->Offset.Green;
|
||||
m_gammaControl.in_offset[2] = pGammaControl->Offset.Blue;
|
||||
|
||||
for (uint32_t i = 0; i < DxgiPresenterGammaRamp::CpCount; i++) {
|
||||
m_gammaControl.cp_values[4 * i + 0] = pGammaControl->GammaCurve[i].Red;
|
||||
m_gammaControl.cp_values[4 * i + 1] = pGammaControl->GammaCurve[i].Green;
|
||||
m_gammaControl.cp_values[4 * i + 2] = pGammaControl->GammaCurve[i].Blue;
|
||||
}
|
||||
|
||||
m_presenter->setGammaRamp(m_gammaControl);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
HRESULT DxgiSwapChain::SetDefaultGammaControl() {
|
||||
std::lock_guard<std::recursive_mutex> lock(m_mutex);
|
||||
|
||||
for (uint32_t i = 0; i < 4; i++) {
|
||||
@ -342,10 +389,10 @@ namespace dxvk {
|
||||
|
||||
|
||||
HRESULT DxgiSwapChain::EnterFullscreenMode(IDXGIOutput *pTarget) {
|
||||
Com<IDXGIOutput> output = pTarget;
|
||||
m_output = static_cast<DxgiOutput*>(pTarget);
|
||||
|
||||
if (output == nullptr) {
|
||||
if (FAILED(GetContainingOutput(&output))) {
|
||||
if (m_output == nullptr) {
|
||||
if (FAILED(GetContainingOutput(reinterpret_cast<IDXGIOutput**>(&m_output)))) {
|
||||
Logger::err("DxgiSwapChain: Failed to enter fullscreen mode: Cannot query containing output");
|
||||
return E_FAIL;
|
||||
}
|
||||
@ -372,7 +419,7 @@ namespace dxvk {
|
||||
|
||||
// Move the window so that it covers the entire output
|
||||
DXGI_OUTPUT_DESC desc;
|
||||
output->GetDesc(&desc);
|
||||
m_output->GetDesc(&desc);
|
||||
|
||||
const RECT rect = desc.DesktopCoordinates;
|
||||
|
||||
@ -380,6 +427,8 @@ namespace dxvk {
|
||||
rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top,
|
||||
SWP_FRAMECHANGED | SWP_SHOWWINDOW | SWP_NOACTIVATE);
|
||||
|
||||
// Assign this swap chain to the output
|
||||
m_output->SetSwapChain(nullptr, this);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
@ -387,6 +436,12 @@ namespace dxvk {
|
||||
HRESULT DxgiSwapChain::LeaveFullscreenMode() {
|
||||
m_desc.Windowed = TRUE;
|
||||
|
||||
// Remove this swap chain from the output
|
||||
if (m_output != nullptr) {
|
||||
m_output->SetSwapChain(this, nullptr);
|
||||
m_output = nullptr;
|
||||
}
|
||||
|
||||
// FIXME wine only restores window flags if the application
|
||||
// has not modified them in the meantime. Some applications
|
||||
// may rely on that behaviour.
|
||||
|
@ -18,6 +18,7 @@ namespace dxvk {
|
||||
|
||||
class DxgiDevice;
|
||||
class DxgiFactory;
|
||||
class DxgiOutput;
|
||||
|
||||
class DxgiSwapChain : public DxgiObject<IDXGISwapChain> {
|
||||
|
||||
@ -80,7 +81,13 @@ namespace dxvk {
|
||||
BOOL Fullscreen,
|
||||
IDXGIOutput *pTarget) final;
|
||||
|
||||
HRESULT SetDefaultGammaRamp();
|
||||
HRESULT GetGammaControl(
|
||||
DXGI_GAMMA_CONTROL* pGammaControl);
|
||||
|
||||
HRESULT SetGammaControl(
|
||||
const DXGI_GAMMA_CONTROL* pGammaControl);
|
||||
|
||||
HRESULT SetDefaultGammaControl();
|
||||
|
||||
private:
|
||||
|
||||
@ -95,6 +102,7 @@ namespace dxvk {
|
||||
Com<DxgiFactory> m_factory;
|
||||
Com<DxgiAdapter> m_adapter;
|
||||
Com<DxgiDevice> m_device;
|
||||
Com<DxgiOutput> m_output;
|
||||
Com<IDXGIVkPresenter> m_presentDevice;
|
||||
|
||||
DXGI_SWAP_CHAIN_DESC m_desc;
|
||||
|
Loading…
Reference in New Issue
Block a user