mirror of
https://github.com/gnif/LookingGlass.git
synced 2024-11-22 13:37:22 +00:00
[host] dxgi: seperate out and implement a post processor chain
This commit is contained in:
parent
e225f66cee
commit
21cd380cad
@ -8,6 +8,8 @@ add_library(capture_DXGI STATIC
|
|||||||
src/ods_capture.c
|
src/ods_capture.c
|
||||||
src/util.c
|
src/util.c
|
||||||
src/com_ref.c
|
src/com_ref.c
|
||||||
|
|
||||||
|
src/pp/sdrwhitelevel.c
|
||||||
)
|
)
|
||||||
|
|
||||||
add_definitions("-DCOBJMACROS -DINITGUID")
|
add_definitions("-DCOBJMACROS -DINITGUID")
|
||||||
|
@ -49,6 +49,16 @@
|
|||||||
|
|
||||||
#define LOCKED(...) INTERLOCKED_SECTION(this->deviceContextLock, __VA_ARGS__)
|
#define LOCKED(...) INTERLOCKED_SECTION(this->deviceContextLock, __VA_ARGS__)
|
||||||
|
|
||||||
|
//post processers
|
||||||
|
extern const DXGIPostProcess DXGIPP_SDRWhiteLevel;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
const DXGIPostProcess * pp;
|
||||||
|
void * opaque;
|
||||||
|
}
|
||||||
|
PostProcessInstance;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
unsigned int id;
|
unsigned int id;
|
||||||
@ -61,12 +71,6 @@ DownsampleRule;
|
|||||||
|
|
||||||
static Vector downsampleRules = {0};
|
static Vector downsampleRules = {0};
|
||||||
|
|
||||||
struct ShaderConsts
|
|
||||||
{
|
|
||||||
float sdrWhiteLevel;
|
|
||||||
}
|
|
||||||
__attribute__((aligned(16)));
|
|
||||||
|
|
||||||
// locals
|
// locals
|
||||||
static struct DXGIInterface * this = NULL;
|
static struct DXGIInterface * this = NULL;
|
||||||
|
|
||||||
@ -82,6 +86,10 @@ static struct DXGICopyBackend * backends[] = {
|
|||||||
static bool dxgi_deinit(void);
|
static bool dxgi_deinit(void);
|
||||||
static CaptureResult dxgi_releaseFrame(void);
|
static CaptureResult dxgi_releaseFrame(void);
|
||||||
|
|
||||||
|
static bool ppInit(const DXGIPostProcess * pp, bool shareable);
|
||||||
|
static ID3D11Texture2D * ppRun(Texture * tex, ID3D11Texture2D * src);
|
||||||
|
static void ppFreeAll(void);
|
||||||
|
|
||||||
// implementation
|
// implementation
|
||||||
|
|
||||||
static const char * dxgi_getName(void)
|
static const char * dxgi_getName(void)
|
||||||
@ -626,18 +634,10 @@ static bool dxgi_init(void)
|
|||||||
IDXGIOutput6_GetDesc1(*output6, &desc1);
|
IDXGIOutput6_GetDesc1(*output6, &desc1);
|
||||||
this->dxgiColorSpace = desc1.ColorSpace;
|
this->dxgiColorSpace = desc1.ColorSpace;
|
||||||
|
|
||||||
if (!getDisplayPathInfo(desc1.Monitor, &this->displayPathInfo))
|
|
||||||
{
|
|
||||||
DEBUG_ERROR("Failed to get the display path info");
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
this->sdrWhiteLevel = getSDRWhiteLevel(&this->displayPathInfo);
|
|
||||||
|
|
||||||
DEBUG_INFO("Bits Per Color : %u" , desc1.BitsPerColor);
|
DEBUG_INFO("Bits Per Color : %u" , desc1.BitsPerColor);
|
||||||
DEBUG_INFO("Color Space : %s" , getDXGIColorSpaceTypeStr(this->dxgiColorSpace));
|
DEBUG_INFO("Color Space : %s" , getDXGIColorSpaceTypeStr(this->dxgiColorSpace));
|
||||||
DEBUG_INFO("Min/Max Luminance : %f/%f", desc1.MinLuminance, desc1.MaxLuminance);
|
DEBUG_INFO("Min/Max Luminance : %f/%f", desc1.MinLuminance, desc1.MaxLuminance);
|
||||||
DEBUG_INFO("Frame Luminance : %f" , desc1.MaxFullFrameLuminance);
|
DEBUG_INFO("Frame Luminance : %f" , desc1.MaxFullFrameLuminance);
|
||||||
DEBUG_INFO("SDR White Level : %f" , this->sdrWhiteLevel);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -753,54 +753,9 @@ static bool dxgi_init(void)
|
|||||||
for (int i = 0; i < this->maxTextures; ++i)
|
for (int i = 0; i < this->maxTextures; ++i)
|
||||||
{
|
{
|
||||||
this->texture[i].texDamageCount = -1;
|
this->texture[i].texDamageCount = -1;
|
||||||
if (!this->hdr)
|
vector_create(&this->texture[i].pp, sizeof(PostProcessInstance), 0);
|
||||||
continue;
|
|
||||||
|
|
||||||
D3D11_TEXTURE2D_DESC hdrTexDesc =
|
|
||||||
{
|
|
||||||
.Width = this->width,
|
|
||||||
.Height = this->height,
|
|
||||||
.MipLevels = 1,
|
|
||||||
.ArraySize = 1,
|
|
||||||
.SampleDesc.Count = 1,
|
|
||||||
.SampleDesc.Quality = 0,
|
|
||||||
.Usage = D3D11_USAGE_DEFAULT,
|
|
||||||
.Format = DXGI_FORMAT_R10G10B10A2_UNORM,
|
|
||||||
.BindFlags = D3D11_BIND_RENDER_TARGET |
|
|
||||||
D3D11_BIND_SHADER_RESOURCE,
|
|
||||||
.CPUAccessFlags = 0,
|
|
||||||
.MiscFlags = 0
|
|
||||||
};
|
|
||||||
|
|
||||||
// allow texture sharing with other backends
|
|
||||||
if (this->backend != ©BackendD3D11)
|
|
||||||
hdrTexDesc.MiscFlags |=
|
|
||||||
D3D11_RESOURCE_MISC_SHARED |
|
|
||||||
D3D11_RESOURCE_MISC_SHARED_NTHANDLE;
|
|
||||||
|
|
||||||
status = ID3D11Device_CreateTexture2D(*this->device, &hdrTexDesc, NULL,
|
|
||||||
(ID3D11Texture2D **)comRef_newGlobal(&this->texture[i].hdrTex));
|
|
||||||
|
|
||||||
if (FAILED(status))
|
|
||||||
{
|
|
||||||
DEBUG_WINERROR("Failed to create HDR texture", status);
|
|
||||||
goto fail;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
status = ID3D11Device_CreateRenderTargetView(*this->device,
|
|
||||||
(ID3D11Resource *)*this->texture[i].hdrTex, NULL,
|
|
||||||
(ID3D11RenderTargetView **)comRef_newGlobal(
|
|
||||||
&this->texture[i].renderTarget));
|
|
||||||
|
|
||||||
if (FAILED(status))
|
|
||||||
{
|
|
||||||
DEBUG_WINERROR("Failed to create HDR target view", status);
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this->hdr)
|
|
||||||
{
|
|
||||||
const D3D11_VIEWPORT vp =
|
const D3D11_VIEWPORT vp =
|
||||||
{
|
{
|
||||||
.TopLeftX = 0.0f,
|
.TopLeftX = 0.0f,
|
||||||
@ -812,126 +767,12 @@ static bool dxgi_init(void)
|
|||||||
};
|
};
|
||||||
ID3D11DeviceContext_RSSetViewports(*this->deviceContext, 1, &vp);
|
ID3D11DeviceContext_RSSetViewports(*this->deviceContext, 1, &vp);
|
||||||
|
|
||||||
static const char * vshader =
|
// if HDR add the SDRWhiteLevel post processor to correct the output
|
||||||
"void main(\n"
|
if (this->hdr && !ppInit(&DXGIPP_SDRWhiteLevel,
|
||||||
" in uint vertexID : SV_VERTEXID,\n"
|
this->backend != ©BackendD3D11))
|
||||||
" out float4 position : SV_POSITION,\n"
|
{
|
||||||
" out float2 texCoord : TEXCOORD0)\n"
|
DEBUG_ERROR("Failed to initialize the SDRWhiteLevel post processor");
|
||||||
"{\n"
|
|
||||||
" float2 positions[4] =\n"
|
|
||||||
" {\n"
|
|
||||||
" float2(-1.0, 1.0),\n"
|
|
||||||
" float2( 1.0, 1.0),\n"
|
|
||||||
" float2(-1.0, -1.0),\n"
|
|
||||||
" float2( 1.0, -1.0)\n"
|
|
||||||
" };\n"
|
|
||||||
"\n"
|
|
||||||
" float2 texCoords[4] =\n"
|
|
||||||
" {\n"
|
|
||||||
" float2(0.0, 0.0),\n"
|
|
||||||
" float2(1.0, 0.0),\n"
|
|
||||||
" float2(0.0, 1.0),\n"
|
|
||||||
" float2(1.0, 1.0)\n"
|
|
||||||
" };\n"
|
|
||||||
"\n"
|
|
||||||
" position = float4(positions[vertexID], 0.0, 1.0);\n"
|
|
||||||
" texCoord = texCoords[vertexID];\n"
|
|
||||||
"}";
|
|
||||||
|
|
||||||
static const char * pshader =
|
|
||||||
"Texture2D gInputTexture : register(t0);\n"
|
|
||||||
"SamplerState gSamplerState : register(s0);\n"
|
|
||||||
"cbuffer gConsts : register(b0)\n"
|
|
||||||
"{\n"
|
|
||||||
" float SDRWhiteLevel;"
|
|
||||||
"};\n"
|
|
||||||
"\n"
|
|
||||||
"float4 main(\n"
|
|
||||||
" float4 position : SV_POSITION,\n"
|
|
||||||
" float2 texCoord : TEXCOORD0) : SV_TARGET"
|
|
||||||
"{\n"
|
|
||||||
" float4 color = gInputTexture.Sample(gSamplerState, texCoord);\n"
|
|
||||||
" color.rgb *= SDRWhiteLevel;\n"
|
|
||||||
" return color;\n"
|
|
||||||
"}\n";
|
|
||||||
|
|
||||||
comRef_defineLocal(ID3DBlob, byteCode);
|
|
||||||
if (!compileShader(byteCode, "main", "vs_5_0", vshader))
|
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
status = ID3D11Device_CreateVertexShader(
|
|
||||||
*this->device,
|
|
||||||
ID3D10Blob_GetBufferPointer(*byteCode),
|
|
||||||
ID3D10Blob_GetBufferSize (*byteCode),
|
|
||||||
NULL,
|
|
||||||
(ID3D11VertexShader **)comRef_newGlobal(&this->vertexShader));
|
|
||||||
|
|
||||||
if (FAILED(status))
|
|
||||||
{
|
|
||||||
DEBUG_WINERROR("Failed to create the vertex shader", status);
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
comRef_release(byteCode);
|
|
||||||
if (!compileShader(byteCode, "main", "ps_5_0", pshader))
|
|
||||||
goto fail;
|
|
||||||
|
|
||||||
status = ID3D11Device_CreatePixelShader(
|
|
||||||
*this->device,
|
|
||||||
ID3D10Blob_GetBufferPointer(*byteCode),
|
|
||||||
ID3D10Blob_GetBufferSize (*byteCode),
|
|
||||||
NULL,
|
|
||||||
(ID3D11PixelShader **)comRef_newGlobal(&this->pixelShader));
|
|
||||||
|
|
||||||
if (FAILED(status))
|
|
||||||
{
|
|
||||||
DEBUG_WINERROR("Failed to create the pixel shader", status);
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
const D3D11_SAMPLER_DESC samplerDesc =
|
|
||||||
{
|
|
||||||
.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR,
|
|
||||||
.AddressU = D3D11_TEXTURE_ADDRESS_WRAP,
|
|
||||||
.AddressV = D3D11_TEXTURE_ADDRESS_WRAP,
|
|
||||||
.AddressW = D3D11_TEXTURE_ADDRESS_WRAP,
|
|
||||||
.ComparisonFunc = D3D11_COMPARISON_NEVER,
|
|
||||||
.MinLOD = 0,
|
|
||||||
.MaxLOD = D3D11_FLOAT32_MAX
|
|
||||||
};
|
|
||||||
|
|
||||||
status = ID3D11Device_CreateSamplerState(
|
|
||||||
*this->device, &samplerDesc,
|
|
||||||
(ID3D11SamplerState **)comRef_newGlobal(&this->samplerState));
|
|
||||||
|
|
||||||
if (FAILED(status))
|
|
||||||
{
|
|
||||||
DEBUG_WINERROR("Failed to create the sampler state", status);
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct ShaderConsts consts =
|
|
||||||
{
|
|
||||||
.sdrWhiteLevel = 80.0f / this->sdrWhiteLevel
|
|
||||||
};
|
|
||||||
|
|
||||||
D3D11_BUFFER_DESC bufferDesc =
|
|
||||||
{
|
|
||||||
.ByteWidth = sizeof(consts),
|
|
||||||
.Usage = D3D11_USAGE_DEFAULT,
|
|
||||||
.BindFlags = D3D11_BIND_CONSTANT_BUFFER,
|
|
||||||
};
|
|
||||||
|
|
||||||
D3D11_SUBRESOURCE_DATA initData = { .pSysMem = &consts };
|
|
||||||
status = ID3D11Device_CreateBuffer(
|
|
||||||
*this->device, &bufferDesc, &initData,
|
|
||||||
(ID3D11Buffer **)comRef_newGlobal(&this->constBuffer));
|
|
||||||
|
|
||||||
if (FAILED(status))
|
|
||||||
{
|
|
||||||
DEBUG_WINERROR("Failed to create the constant buffer", status);
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < LGMP_Q_FRAME_LEN; ++i)
|
for (int i = 0; i < LGMP_Q_FRAME_LEN; ++i)
|
||||||
@ -961,19 +802,20 @@ static bool dxgi_deinit(void)
|
|||||||
|
|
||||||
for (int i = 0; i < this->maxTextures; ++i)
|
for (int i = 0; i < this->maxTextures; ++i)
|
||||||
{
|
{
|
||||||
if (this->texture[i].map)
|
Texture * tex = &this->texture[i];
|
||||||
{
|
if (!tex->map)
|
||||||
this->backend->unmapTexture(this->texture + i);
|
continue;
|
||||||
this->texture[i].map = NULL;
|
this->backend->unmapTexture(tex);
|
||||||
}
|
tex->map = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this->dup && *this->dup)
|
if (this->dup && *this->dup)
|
||||||
dxgi_releaseFrame();
|
dxgi_releaseFrame();
|
||||||
|
|
||||||
// this MUST run before backend->free().
|
// this MUST run before backend->free() & ppFreeAll.
|
||||||
comRef_free();
|
comRef_free();
|
||||||
|
|
||||||
|
ppFreeAll();
|
||||||
if (this->backend)
|
if (this->backend)
|
||||||
{
|
{
|
||||||
this->backend->free();
|
this->backend->free();
|
||||||
@ -1223,77 +1065,15 @@ static CaptureResult dxgi_capture(void)
|
|||||||
computeFrameDamage(tex);
|
computeFrameDamage(tex);
|
||||||
computeTexDamage(tex);
|
computeTexDamage(tex);
|
||||||
|
|
||||||
if (this->hdr)
|
ID3D11Texture2D * dst = ppRun(tex, *src);
|
||||||
{
|
if (dst != *src)
|
||||||
// setup the pixel shader input resource view
|
|
||||||
comRef_defineLocal(ID3D11ShaderResourceView, inputSRV);
|
|
||||||
{
|
|
||||||
const D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc =
|
|
||||||
{
|
|
||||||
.Format = this->dxgiSrcFormat,
|
|
||||||
.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D,
|
|
||||||
.Texture2D.MipLevels = 1
|
|
||||||
};
|
|
||||||
status = ID3D11Device_CreateShaderResourceView(
|
|
||||||
*this->device, (ID3D11Resource *)*src, &srvDesc, inputSRV);
|
|
||||||
if (FAILED(status))
|
|
||||||
{
|
|
||||||
DEBUG_WINERROR("Failed to create the source resource view", status);
|
|
||||||
result = CAPTURE_RESULT_ERROR;
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
float nits = getSDRWhiteLevel(&this->displayPathInfo);
|
|
||||||
if (nits != this->sdrWhiteLevel)
|
|
||||||
{
|
|
||||||
this->sdrWhiteLevel = nits;
|
|
||||||
|
|
||||||
struct ShaderConsts consts =
|
|
||||||
{
|
|
||||||
.sdrWhiteLevel = 80.0f / nits
|
|
||||||
};
|
|
||||||
|
|
||||||
ID3D11DeviceContext_UpdateSubresource(
|
|
||||||
*this->deviceContext, (ID3D11Resource*)*this->constBuffer,
|
|
||||||
0, NULL, &consts, 0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
ID3D11DeviceContext_VSSetShader(
|
|
||||||
*this->deviceContext, *this->vertexShader, NULL, 0);
|
|
||||||
|
|
||||||
ID3D11DeviceContext_PSSetShader(
|
|
||||||
*this->deviceContext, *this->pixelShader, NULL, 0);
|
|
||||||
ID3D11DeviceContext_PSSetShaderResources(
|
|
||||||
*this->deviceContext, 0, 1, inputSRV);
|
|
||||||
ID3D11DeviceContext_PSSetSamplers(
|
|
||||||
*this->deviceContext, 0, 1, this->samplerState);
|
|
||||||
ID3D11DeviceContext_PSSetConstantBuffers(
|
|
||||||
*this->deviceContext, 0, 1, this->constBuffer);
|
|
||||||
|
|
||||||
ID3D11DeviceContext_OMSetRenderTargets(
|
|
||||||
*this->deviceContext, 1, tex->renderTarget, NULL);
|
|
||||||
|
|
||||||
ID3D11DeviceContext_IASetPrimitiveTopology(
|
|
||||||
*this->deviceContext, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
|
|
||||||
|
|
||||||
ID3D11DeviceContext_Draw(*this->deviceContext, 4, 0);
|
|
||||||
ID3D11DeviceContext_Flush(*this->deviceContext);
|
ID3D11DeviceContext_Flush(*this->deviceContext);
|
||||||
|
|
||||||
if (!this->backend->copyFrame(tex, *tex->hdrTex))
|
if (!this->backend->copyFrame(tex, dst))
|
||||||
{
|
{
|
||||||
result = CAPTURE_RESULT_ERROR;
|
result = CAPTURE_RESULT_ERROR;
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (!this->backend->copyFrame(tex, *src))
|
|
||||||
{
|
|
||||||
result = CAPTURE_RESULT_ERROR;
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < this->maxTextures; ++i)
|
for (int i = 0; i < this->maxTextures; ++i)
|
||||||
{
|
{
|
||||||
@ -1535,6 +1315,51 @@ static CaptureResult dxgi_releaseFrame(void)
|
|||||||
return CAPTURE_RESULT_OK;
|
return CAPTURE_RESULT_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool ppInit(const DXGIPostProcess * pp, bool shareable)
|
||||||
|
{
|
||||||
|
if (!pp->setup(this->device, this->deviceContext, this->output))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for(int i = 0; i < this->maxTextures; ++i)
|
||||||
|
{
|
||||||
|
PostProcessInstance inst = { .pp = pp };
|
||||||
|
if (!pp->init(&inst.opaque, this->width, this->height, shareable))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
vector_push(&this->texture[i].pp, &inst);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ID3D11Texture2D * ppRun(Texture * tex, ID3D11Texture2D * src)
|
||||||
|
{
|
||||||
|
PostProcessInstance * inst;
|
||||||
|
vector_forEachRef(inst, &tex->pp)
|
||||||
|
src = inst->pp->run(inst->opaque, src);
|
||||||
|
|
||||||
|
return src;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ppFreeAll(void)
|
||||||
|
{
|
||||||
|
for(int i = 0; i < this->maxTextures; ++i)
|
||||||
|
{
|
||||||
|
Texture * tex = &this->texture[i];
|
||||||
|
if (!tex->pp.data)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
PostProcessInstance * inst;
|
||||||
|
vector_forEachRef(inst, &tex->pp)
|
||||||
|
{
|
||||||
|
inst->pp->free(inst->opaque);
|
||||||
|
if (i == this->maxTextures - 1)
|
||||||
|
inst->pp->finish();
|
||||||
|
}
|
||||||
|
vector_destroy(&tex->pp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct CaptureInterface Capture_DXGI =
|
struct CaptureInterface Capture_DXGI =
|
||||||
{
|
{
|
||||||
.shortName = "DXGI",
|
.shortName = "DXGI",
|
||||||
|
@ -18,6 +18,8 @@
|
|||||||
* Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
* Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "pp.h"
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <dxgi.h>
|
#include <dxgi.h>
|
||||||
#include <dxgi1_2.h>
|
#include <dxgi1_2.h>
|
||||||
@ -28,6 +30,7 @@
|
|||||||
#include "common/event.h"
|
#include "common/event.h"
|
||||||
#include "common/locking.h"
|
#include "common/locking.h"
|
||||||
#include "common/types.h"
|
#include "common/types.h"
|
||||||
|
#include "common/vector.h"
|
||||||
#include "interface/capture.h"
|
#include "interface/capture.h"
|
||||||
|
|
||||||
enum TextureState
|
enum TextureState
|
||||||
@ -47,8 +50,9 @@ typedef struct Texture
|
|||||||
FrameDamageRect damageRects[KVMFR_MAX_DAMAGE_RECTS];
|
FrameDamageRect damageRects[KVMFR_MAX_DAMAGE_RECTS];
|
||||||
int32_t texDamageCount;
|
int32_t texDamageCount;
|
||||||
FrameDamageRect texDamageRects[KVMFR_MAX_DAMAGE_RECTS];
|
FrameDamageRect texDamageRects[KVMFR_MAX_DAMAGE_RECTS];
|
||||||
ID3D11RenderTargetView ** renderTarget;
|
|
||||||
ID3D11Texture2D ** hdrTex;
|
// post processing
|
||||||
|
Vector pp;
|
||||||
|
|
||||||
void * impl;
|
void * impl;
|
||||||
}
|
}
|
||||||
@ -89,13 +93,7 @@ struct DXGIInterface
|
|||||||
bool needsRelease;
|
bool needsRelease;
|
||||||
DXGI_FORMAT dxgiSrcFormat, dxgiFormat;
|
DXGI_FORMAT dxgiSrcFormat, dxgiFormat;
|
||||||
bool hdr;
|
bool hdr;
|
||||||
DISPLAYCONFIG_PATH_INFO displayPathInfo;
|
|
||||||
DXGI_COLOR_SPACE_TYPE dxgiColorSpace;
|
DXGI_COLOR_SPACE_TYPE dxgiColorSpace;
|
||||||
float sdrWhiteLevel;
|
|
||||||
ID3D11Buffer ** constBuffer;
|
|
||||||
ID3D11PixelShader ** pixelShader;
|
|
||||||
ID3D11VertexShader ** vertexShader;
|
|
||||||
ID3D11SamplerState ** samplerState;
|
|
||||||
struct DXGICopyBackend * backend;
|
struct DXGICopyBackend * backend;
|
||||||
|
|
||||||
CaptureGetPointerBuffer getPointerBufferFn;
|
CaptureGetPointerBuffer getPointerBufferFn;
|
||||||
|
54
host/platform/Windows/capture/DXGI/src/pp.h
Normal file
54
host/platform/Windows/capture/DXGI/src/pp.h
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
/**
|
||||||
|
* Looking Glass
|
||||||
|
* Copyright © 2017-2023 The Looking Glass Authors
|
||||||
|
* https://looking-glass.io
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License as published by the Free
|
||||||
|
* Software Foundation; either version 2 of the License, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program; if not, write to the Free Software Foundation, Inc., 59
|
||||||
|
* Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <d3d11.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
/* the friendly name of the processor for debugging */
|
||||||
|
const char * name;
|
||||||
|
|
||||||
|
/* early initialization for registering options */
|
||||||
|
void (*earlyInit)(void);
|
||||||
|
|
||||||
|
/* common setup */
|
||||||
|
bool (*setup)(
|
||||||
|
ID3D11Device ** device,
|
||||||
|
ID3D11DeviceContext ** context,
|
||||||
|
IDXGIOutput ** output);
|
||||||
|
|
||||||
|
/* instance initialization */
|
||||||
|
bool (*init)(
|
||||||
|
void ** opaque,
|
||||||
|
int width,
|
||||||
|
int height,
|
||||||
|
bool shareable);
|
||||||
|
|
||||||
|
/* perform the processing */
|
||||||
|
ID3D11Texture2D * (*run)(void * opaque, ID3D11Texture2D * src);
|
||||||
|
|
||||||
|
/* instance destruction */
|
||||||
|
void (*free)(void * opaque);
|
||||||
|
|
||||||
|
/* cleanup */
|
||||||
|
void (*finish)(void);
|
||||||
|
}
|
||||||
|
DXGIPostProcess;
|
377
host/platform/Windows/capture/DXGI/src/pp/sdrwhitelevel.c
Normal file
377
host/platform/Windows/capture/DXGI/src/pp/sdrwhitelevel.c
Normal file
@ -0,0 +1,377 @@
|
|||||||
|
/**
|
||||||
|
* Looking Glass
|
||||||
|
* Copyright © 2017-2023 The Looking Glass Authors
|
||||||
|
* https://looking-glass.io
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License as published by the Free
|
||||||
|
* Software Foundation; either version 2 of the License, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program; if not, write to the Free Software Foundation, Inc., 59
|
||||||
|
* Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "pp.h"
|
||||||
|
#include "com_ref.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
#include "common/debug.h"
|
||||||
|
#include "common/windebug.h"
|
||||||
|
|
||||||
|
#include <dxgi1_6.h>
|
||||||
|
|
||||||
|
typedef struct SDRWhiteLevel
|
||||||
|
{
|
||||||
|
ID3D11Device ** device;
|
||||||
|
ID3D11DeviceContext ** context;
|
||||||
|
|
||||||
|
ID3D11VertexShader ** vshader;
|
||||||
|
ID3D11PixelShader ** pshader;
|
||||||
|
ID3D11SamplerState ** sampler;
|
||||||
|
ID3D11Buffer ** buffer;
|
||||||
|
|
||||||
|
DISPLAYCONFIG_PATH_INFO displayPathInfo;
|
||||||
|
float sdrWhiteLevel;
|
||||||
|
}
|
||||||
|
SDRWhiteLevel;
|
||||||
|
SDRWhiteLevel this = {0};
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
ID3D11Texture2D ** tex;
|
||||||
|
ID3D11RenderTargetView ** target;
|
||||||
|
}
|
||||||
|
SDRWhiteLevelInst;
|
||||||
|
|
||||||
|
struct ShaderConsts
|
||||||
|
{
|
||||||
|
float sdrWhiteLevel;
|
||||||
|
}
|
||||||
|
__attribute__((aligned(16)));
|
||||||
|
|
||||||
|
static const char * vshader =
|
||||||
|
"void main(\n"
|
||||||
|
" in uint vertexID : SV_VERTEXID,\n"
|
||||||
|
" out float4 position : SV_POSITION,\n"
|
||||||
|
" out float2 texCoord : TEXCOORD0)\n"
|
||||||
|
"{\n"
|
||||||
|
" float2 positions[4] =\n"
|
||||||
|
" {\n"
|
||||||
|
" float2(-1.0, 1.0),\n"
|
||||||
|
" float2( 1.0, 1.0),\n"
|
||||||
|
" float2(-1.0, -1.0),\n"
|
||||||
|
" float2( 1.0, -1.0)\n"
|
||||||
|
" };\n"
|
||||||
|
"\n"
|
||||||
|
" float2 texCoords[4] =\n"
|
||||||
|
" {\n"
|
||||||
|
" float2(0.0, 0.0),\n"
|
||||||
|
" float2(1.0, 0.0),\n"
|
||||||
|
" float2(0.0, 1.0),\n"
|
||||||
|
" float2(1.0, 1.0)\n"
|
||||||
|
" };\n"
|
||||||
|
"\n"
|
||||||
|
" position = float4(positions[vertexID], 0.0, 1.0);\n"
|
||||||
|
" texCoord = texCoords[vertexID];\n"
|
||||||
|
"}";
|
||||||
|
|
||||||
|
static const char * pshader =
|
||||||
|
"Texture2D gInputTexture : register(t0);\n"
|
||||||
|
"SamplerState gSamplerState : register(s0);\n"
|
||||||
|
"cbuffer gConsts : register(b0)\n"
|
||||||
|
"{\n"
|
||||||
|
" float SDRWhiteLevel;"
|
||||||
|
"};\n"
|
||||||
|
"\n"
|
||||||
|
"float4 main(\n"
|
||||||
|
" float4 position : SV_POSITION,\n"
|
||||||
|
" float2 texCoord : TEXCOORD0) : SV_TARGET"
|
||||||
|
"{\n"
|
||||||
|
" float4 color = gInputTexture.Sample(gSamplerState, texCoord);\n"
|
||||||
|
" color.rgb *= SDRWhiteLevel;\n"
|
||||||
|
" return color;\n"
|
||||||
|
"}\n";
|
||||||
|
|
||||||
|
static void updateConsts(void);
|
||||||
|
|
||||||
|
static bool sdrWhiteLevel_setup(
|
||||||
|
ID3D11Device ** device,
|
||||||
|
ID3D11DeviceContext ** context,
|
||||||
|
IDXGIOutput ** output
|
||||||
|
)
|
||||||
|
{
|
||||||
|
bool result = false;
|
||||||
|
comRef_scopePush();
|
||||||
|
HRESULT status;
|
||||||
|
|
||||||
|
this.device = device;
|
||||||
|
this.context = context;
|
||||||
|
|
||||||
|
comRef_defineLocal(IDXGIOutput6, output6);
|
||||||
|
status = IDXGIOutput_QueryInterface(
|
||||||
|
*output, &IID_IDXGIOutput6, (void **)output6);
|
||||||
|
|
||||||
|
if (!SUCCEEDED(status))
|
||||||
|
{
|
||||||
|
DEBUG_ERROR("Failed to get the IDXGIOutput6 interface");
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
DXGI_OUTPUT_DESC1 desc1;
|
||||||
|
IDXGIOutput6_GetDesc1(*output6, &desc1);
|
||||||
|
if (!getDisplayPathInfo(desc1.Monitor, &this.displayPathInfo))
|
||||||
|
{
|
||||||
|
DEBUG_ERROR("Failed to get the display path info");
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// compile and create the vertex shader
|
||||||
|
comRef_defineLocal(ID3DBlob, byteCode);
|
||||||
|
if (!compileShader(byteCode, "main", "vs_5_0", vshader))
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
status = ID3D11Device_CreateVertexShader(
|
||||||
|
*this.device,
|
||||||
|
ID3D10Blob_GetBufferPointer(*byteCode),
|
||||||
|
ID3D10Blob_GetBufferSize (*byteCode),
|
||||||
|
NULL,
|
||||||
|
(ID3D11VertexShader **)comRef_newGlobal(&this.vshader));
|
||||||
|
|
||||||
|
if (FAILED(status))
|
||||||
|
{
|
||||||
|
DEBUG_WINERROR("Failed to create the vertex shader", status);
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
comRef_release(byteCode);
|
||||||
|
if (!compileShader(byteCode, "main", "ps_5_0", pshader))
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
status = ID3D11Device_CreatePixelShader(
|
||||||
|
*this.device,
|
||||||
|
ID3D10Blob_GetBufferPointer(*byteCode),
|
||||||
|
ID3D10Blob_GetBufferSize (*byteCode),
|
||||||
|
NULL,
|
||||||
|
(ID3D11PixelShader **)comRef_newGlobal(&this.pshader));
|
||||||
|
|
||||||
|
if (FAILED(status))
|
||||||
|
{
|
||||||
|
DEBUG_WINERROR("Failed to create the pixel shader", status);
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
const D3D11_SAMPLER_DESC samplerDesc =
|
||||||
|
{
|
||||||
|
.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR,
|
||||||
|
.AddressU = D3D11_TEXTURE_ADDRESS_WRAP,
|
||||||
|
.AddressV = D3D11_TEXTURE_ADDRESS_WRAP,
|
||||||
|
.AddressW = D3D11_TEXTURE_ADDRESS_WRAP,
|
||||||
|
.ComparisonFunc = D3D11_COMPARISON_NEVER,
|
||||||
|
.MinLOD = 0,
|
||||||
|
.MaxLOD = D3D11_FLOAT32_MAX
|
||||||
|
};
|
||||||
|
|
||||||
|
status = ID3D11Device_CreateSamplerState(
|
||||||
|
*this.device, &samplerDesc,
|
||||||
|
(ID3D11SamplerState **)comRef_newGlobal(&this.sampler));
|
||||||
|
|
||||||
|
if (FAILED(status))
|
||||||
|
{
|
||||||
|
DEBUG_WINERROR("Failed to create the sampler state", status);
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
D3D11_BUFFER_DESC bufferDesc =
|
||||||
|
{
|
||||||
|
.ByteWidth = sizeof(struct ShaderConsts),
|
||||||
|
.Usage = D3D11_USAGE_DEFAULT,
|
||||||
|
.BindFlags = D3D11_BIND_CONSTANT_BUFFER,
|
||||||
|
};
|
||||||
|
|
||||||
|
status = ID3D11Device_CreateBuffer(
|
||||||
|
*this.device, &bufferDesc, NULL,
|
||||||
|
(ID3D11Buffer **)comRef_newGlobal(&this.buffer));
|
||||||
|
|
||||||
|
if (FAILED(status))
|
||||||
|
{
|
||||||
|
DEBUG_WINERROR("Failed to create the constant buffer", status);
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
updateConsts();
|
||||||
|
DEBUG_INFO("SDR White Level : %f" , this.sdrWhiteLevel);
|
||||||
|
|
||||||
|
result = true;
|
||||||
|
|
||||||
|
exit:
|
||||||
|
comRef_scopePop();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sdrWhiteLevel_finish(void)
|
||||||
|
{
|
||||||
|
memset(&this, 0, sizeof(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool sdrWhiteLevel_init(
|
||||||
|
void ** opaque,
|
||||||
|
int width,
|
||||||
|
int height,
|
||||||
|
bool shareable)
|
||||||
|
{
|
||||||
|
SDRWhiteLevelInst * inst = (SDRWhiteLevelInst *)calloc(1, sizeof(*inst));
|
||||||
|
if (!inst)
|
||||||
|
{
|
||||||
|
DEBUG_ERROR("Failed to allocate memory");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
comRef_scopePush();
|
||||||
|
|
||||||
|
// create the output texture
|
||||||
|
D3D11_TEXTURE2D_DESC texDesc =
|
||||||
|
{
|
||||||
|
.Width = width,
|
||||||
|
.Height = height,
|
||||||
|
.MipLevels = 1,
|
||||||
|
.ArraySize = 1,
|
||||||
|
.SampleDesc.Count = 1,
|
||||||
|
.SampleDesc.Quality = 0,
|
||||||
|
.Usage = D3D11_USAGE_DEFAULT,
|
||||||
|
.Format = DXGI_FORMAT_R10G10B10A2_UNORM,
|
||||||
|
.BindFlags = D3D11_BIND_RENDER_TARGET |
|
||||||
|
D3D11_BIND_SHADER_RESOURCE,
|
||||||
|
.CPUAccessFlags = 0,
|
||||||
|
.MiscFlags = 0
|
||||||
|
};
|
||||||
|
|
||||||
|
// allow texture sharing with other backends
|
||||||
|
if (shareable)
|
||||||
|
texDesc.MiscFlags |=
|
||||||
|
D3D11_RESOURCE_MISC_SHARED |
|
||||||
|
D3D11_RESOURCE_MISC_SHARED_NTHANDLE;
|
||||||
|
|
||||||
|
comRef_defineLocal(ID3D11Texture2D, tex);
|
||||||
|
HRESULT status = ID3D11Device_CreateTexture2D(
|
||||||
|
*this.device, &texDesc, NULL, tex);
|
||||||
|
|
||||||
|
if (FAILED(status))
|
||||||
|
{
|
||||||
|
DEBUG_WINERROR("Failed to create the output texture", status);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
comRef_defineLocal(ID3D11RenderTargetView, target);
|
||||||
|
status = ID3D11Device_CreateRenderTargetView(
|
||||||
|
*this.device, *(ID3D11Resource **)tex, NULL, target);
|
||||||
|
|
||||||
|
if (FAILED(status))
|
||||||
|
{
|
||||||
|
DEBUG_WINERROR("Failed to create the render target view", status);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
*opaque = inst;
|
||||||
|
comRef_toGlobal(inst->tex , tex );
|
||||||
|
comRef_toGlobal(inst->target, target);
|
||||||
|
|
||||||
|
comRef_scopePop();
|
||||||
|
return true;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
comRef_scopePop();
|
||||||
|
free(inst);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sdrWhiteLevel_free(void * opaque)
|
||||||
|
{
|
||||||
|
SDRWhiteLevelInst * inst = (SDRWhiteLevelInst *)opaque;
|
||||||
|
comRef_release(inst->target);
|
||||||
|
comRef_release(inst->tex );
|
||||||
|
free(inst);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void updateConsts(void)
|
||||||
|
{
|
||||||
|
float nits = getSDRWhiteLevel(&this.displayPathInfo);
|
||||||
|
if (nits == this.sdrWhiteLevel)
|
||||||
|
return;
|
||||||
|
|
||||||
|
this.sdrWhiteLevel = nits;
|
||||||
|
|
||||||
|
struct ShaderConsts consts = { .sdrWhiteLevel = 80.0f / nits };
|
||||||
|
ID3D11DeviceContext_UpdateSubresource(
|
||||||
|
*this.context, *(ID3D11Resource**)this.buffer,
|
||||||
|
0, NULL, &consts, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ID3D11Texture2D * sdrWhiteLevel_run(void * opaque, ID3D11Texture2D * src)
|
||||||
|
{
|
||||||
|
comRef_scopePush();
|
||||||
|
ID3D11Texture2D * result = NULL;
|
||||||
|
SDRWhiteLevelInst * inst = (SDRWhiteLevelInst *)opaque;
|
||||||
|
HRESULT status;
|
||||||
|
|
||||||
|
updateConsts();
|
||||||
|
|
||||||
|
// setup the pixel shader input resource view
|
||||||
|
comRef_defineLocal(ID3D11ShaderResourceView, inputSRV);
|
||||||
|
D3D11_TEXTURE2D_DESC desc;
|
||||||
|
ID3D11Texture2D_GetDesc(src, &desc);
|
||||||
|
|
||||||
|
const D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc =
|
||||||
|
{
|
||||||
|
.Format = desc.Format,
|
||||||
|
.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D,
|
||||||
|
.Texture2D.MipLevels = 1
|
||||||
|
};
|
||||||
|
status = ID3D11Device_CreateShaderResourceView(
|
||||||
|
*this.device, (ID3D11Resource *)src, &srvDesc, inputSRV);
|
||||||
|
if (FAILED(status))
|
||||||
|
{
|
||||||
|
DEBUG_WINERROR("Failed to create the source resource view", status);
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// set the vertex and pixel shader
|
||||||
|
ID3D11DeviceContext_VSSetShader(*this.context, *this.vshader, NULL, 0);
|
||||||
|
ID3D11DeviceContext_PSSetShader(*this.context, *this.pshader, NULL, 0);
|
||||||
|
|
||||||
|
// set the pixel shader resources
|
||||||
|
ID3D11DeviceContext_PSSetShaderResources(*this.context, 0, 1, inputSRV );
|
||||||
|
ID3D11DeviceContext_PSSetSamplers (*this.context, 0, 1, this.sampler);
|
||||||
|
ID3D11DeviceContext_PSSetConstantBuffers(*this.context, 0, 1, this.buffer );
|
||||||
|
|
||||||
|
// set the render target
|
||||||
|
ID3D11DeviceContext_OMSetRenderTargets(*this.context, 1, inst->target, NULL);
|
||||||
|
|
||||||
|
ID3D11DeviceContext_IASetPrimitiveTopology(
|
||||||
|
*this.context, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
|
||||||
|
|
||||||
|
ID3D11DeviceContext_Draw(*this.context, 4, 0);
|
||||||
|
|
||||||
|
result = *inst->tex;
|
||||||
|
|
||||||
|
exit:
|
||||||
|
comRef_scopePop();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
DXGIPostProcess DXGIPP_SDRWhiteLevel =
|
||||||
|
{
|
||||||
|
.name = "SDRWhiteLevel",
|
||||||
|
.earlyInit = NULL,
|
||||||
|
.setup = sdrWhiteLevel_setup,
|
||||||
|
.init = sdrWhiteLevel_init,
|
||||||
|
.free = sdrWhiteLevel_free,
|
||||||
|
.run = sdrWhiteLevel_run,
|
||||||
|
.finish = sdrWhiteLevel_finish
|
||||||
|
};
|
Loading…
Reference in New Issue
Block a user