1
0
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:
Philip Rebohle 2018-04-10 22:07:25 +02:00
parent ad7f0971cf
commit dd3f4c89ac
No known key found for this signature in database
GPG Key ID: C8CC613427A31C99
4 changed files with 126 additions and 17 deletions

View File

@ -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;

View File

@ -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;
};

View File

@ -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.

View File

@ -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;