mirror of
https://github.com/gnif/LookingGlass.git
synced 2024-12-22 13:52:57 +00:00
[host] DXGI: initial implementation of RGB24 support
This commit breaks damage tracking and the dx12 backend and is not in a state where it should be used by the general public.
This commit is contained in:
parent
b3879ff1d7
commit
578d98fd22
16 changed files with 559 additions and 232 deletions
|
@ -28,7 +28,7 @@
|
|||
#include "types.h"
|
||||
|
||||
#define KVMFR_MAGIC "KVMFR---"
|
||||
#define KVMFR_VERSION 19
|
||||
#define KVMFR_VERSION 20
|
||||
|
||||
#define KVMFR_MAX_DAMAGE_RECTS 64
|
||||
|
||||
|
@ -149,6 +149,8 @@ typedef struct KVMFRFrame
|
|||
FrameType type; // the frame data type
|
||||
uint32_t screenWidth; // the client's screen width
|
||||
uint32_t screenHeight; // the client's screen height
|
||||
uint32_t dataWidth; // the packed width of the frame data
|
||||
uint32_t dataHeight; // the packed height of the frame data
|
||||
uint32_t frameWidth; // the frame width
|
||||
uint32_t frameHeight; // the frame height
|
||||
FrameRotation rotation; // the frame rotation
|
||||
|
|
|
@ -55,6 +55,7 @@ typedef enum FrameType
|
|||
FRAME_TYPE_RGBA , // RGBA interleaved: R,G,B,A 32bpp
|
||||
FRAME_TYPE_RGBA10 , // RGBA interleaved: R,G,B,A 10,10,10,2 bpp
|
||||
FRAME_TYPE_RGBA16F , // RGBA interleaved: R,G,B,A 16,16,16,16 bpp float
|
||||
FRAME_TYPE_BGR , // BGR interleaved: B,G,R 24bpp
|
||||
FRAME_TYPE_MAX , // sentinel value
|
||||
}
|
||||
FrameType;
|
||||
|
|
|
@ -26,5 +26,6 @@ const char * FrameTypeStr[FRAME_TYPE_MAX] =
|
|||
"FRAME_TYPE_BGRA",
|
||||
"FRAME_TYPE_RGBA",
|
||||
"FRAME_TYPE_RGBA10",
|
||||
"FRAME_TYPE_RGBA16F"
|
||||
"FRAME_TYPE_RGBA16F",
|
||||
"FRAME_TYPE_BGR"
|
||||
};
|
||||
|
|
|
@ -48,6 +48,7 @@ typedef enum CaptureFormat
|
|||
CAPTURE_FMT_RGBA ,
|
||||
CAPTURE_FMT_RGBA10 ,
|
||||
CAPTURE_FMT_RGBA16F,
|
||||
CAPTURE_FMT_BGR ,
|
||||
|
||||
// pointer formats
|
||||
CAPTURE_FMT_COLOR ,
|
||||
|
@ -69,18 +70,21 @@ CaptureRotation;
|
|||
|
||||
typedef struct CaptureFrame
|
||||
{
|
||||
unsigned int formatVer;
|
||||
unsigned int screenWidth;
|
||||
unsigned int screenHeight;
|
||||
unsigned int frameWidth;
|
||||
unsigned int frameHeight;
|
||||
bool truncated;
|
||||
unsigned int pitch;
|
||||
unsigned int stride;
|
||||
CaptureFormat format;
|
||||
bool hdr;
|
||||
bool hdrPQ;
|
||||
CaptureRotation rotation;
|
||||
unsigned formatVer;
|
||||
unsigned screenWidth; // actual screen width
|
||||
unsigned screenHeight; // actual screen height
|
||||
unsigned dataWidth; // the width of the packed frame data
|
||||
unsigned dataHeight; // the height of the packed frame data
|
||||
unsigned frameWidth; // width of the frame image
|
||||
unsigned frameHeight; // height of the frame image
|
||||
unsigned pitch; // total width of one row of data in bytes
|
||||
unsigned stride; // total width of one row of data in pixels
|
||||
CaptureFormat format; // the data format of the frame
|
||||
bool truncated; // true if the frame data is truncated
|
||||
bool hdr; // true if the frame format is HDR
|
||||
bool hdrPQ; // true if the frame format is PQ transformed
|
||||
CaptureRotation rotation; // output rotation of the frame
|
||||
|
||||
uint32_t damageRectsCount;
|
||||
FrameDamageRect damageRects[KVMFR_MAX_DAMAGE_RECTS];
|
||||
}
|
||||
|
@ -94,9 +98,9 @@ typedef struct CapturePointer
|
|||
|
||||
bool shapeUpdate;
|
||||
CaptureFormat format;
|
||||
unsigned int hx, hy;
|
||||
unsigned int width, height;
|
||||
unsigned int pitch;
|
||||
unsigned hx, hy;
|
||||
unsigned width, height;
|
||||
unsigned pitch;
|
||||
}
|
||||
CapturePointer;
|
||||
|
||||
|
@ -123,6 +127,6 @@ typedef struct CaptureInterface
|
|||
|
||||
CaptureResult (*capture )(void);
|
||||
CaptureResult (*waitFrame )(CaptureFrame * frame, const size_t maxFrameSize);
|
||||
CaptureResult (*getFrame )(FrameBuffer * frame, const unsigned int height, int frameIndex);
|
||||
CaptureResult (*getFrame )(FrameBuffer * frame, int frameIndex);
|
||||
}
|
||||
CaptureInterface;
|
||||
|
|
|
@ -10,6 +10,7 @@ add_library(capture_DXGI STATIC
|
|||
src/com_ref.c
|
||||
|
||||
src/pp/sdrwhitelevel.c
|
||||
src/pp/rgb24.c
|
||||
)
|
||||
|
||||
add_definitions("-DCOBJMACROS -DINITGUID")
|
||||
|
|
|
@ -35,9 +35,7 @@ struct D3D11Backend
|
|||
|
||||
struct D3D11TexImpl
|
||||
{
|
||||
ID3D11Texture2D ** gpu;
|
||||
ID3D11Texture2D ** cpu;
|
||||
ID3D11ShaderResourceView ** srv;
|
||||
ID3D11Texture2D ** cpu;
|
||||
};
|
||||
|
||||
#define TEXIMPL(x) ((struct D3D11TexImpl *)(x).impl)
|
||||
|
@ -49,7 +47,6 @@ static void d3d11_free(void);
|
|||
|
||||
static bool d3d11_create(struct DXGIInterface * intf)
|
||||
{
|
||||
HRESULT status;
|
||||
dxgi = intf;
|
||||
|
||||
DEBUG_ASSERT(!this);
|
||||
|
@ -61,32 +58,24 @@ static bool d3d11_create(struct DXGIInterface * intf)
|
|||
}
|
||||
|
||||
this->avgMapTime = runningavg_new(10);
|
||||
return true;
|
||||
}
|
||||
|
||||
D3D11_TEXTURE2D_DESC gpuTexDesc =
|
||||
{
|
||||
.Width = dxgi->width,
|
||||
.Height = dxgi->height,
|
||||
.MipLevels = dxgi->downsampleLevel + 1,
|
||||
.ArraySize = 1,
|
||||
.SampleDesc.Count = 1,
|
||||
.SampleDesc.Quality = 0,
|
||||
.Usage = D3D11_USAGE_DEFAULT,
|
||||
.Format = dxgi->dxgiFormat,
|
||||
.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE,
|
||||
.CPUAccessFlags = 0,
|
||||
.MiscFlags = D3D11_RESOURCE_MISC_GENERATE_MIPS
|
||||
};
|
||||
static bool d3d11_configure(unsigned width, unsigned height, DXGI_FORMAT format,
|
||||
unsigned * pitch)
|
||||
{
|
||||
HRESULT status;
|
||||
|
||||
D3D11_TEXTURE2D_DESC cpuTexDesc =
|
||||
{
|
||||
.Width = dxgi->targetWidth,
|
||||
.Height = dxgi->targetHeight,
|
||||
.Width = width,
|
||||
.Height = height,
|
||||
.MipLevels = 1,
|
||||
.ArraySize = 1,
|
||||
.SampleDesc.Count = 1,
|
||||
.SampleDesc.Quality = 0,
|
||||
.Usage = D3D11_USAGE_STAGING,
|
||||
.Format = dxgi->dxgiFormat,
|
||||
.Format = format,
|
||||
.BindFlags = 0,
|
||||
.CPUAccessFlags = D3D11_CPU_ACCESS_READ,
|
||||
.MiscFlags = 0
|
||||
|
@ -111,22 +100,6 @@ static bool d3d11_create(struct DXGIInterface * intf)
|
|||
DEBUG_WINERROR("Failed to create CPU texture", status);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!dxgi->downsampleLevel)
|
||||
continue;
|
||||
|
||||
status = ID3D11Device_CreateTexture2D(*dxgi->device, &gpuTexDesc, NULL,
|
||||
(ID3D11Texture2D **)comRef_newGlobal(&teximpl->gpu));
|
||||
|
||||
if (FAILED(status))
|
||||
{
|
||||
DEBUG_WINERROR("Failed to create GPU texture", status);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ID3D11Device_CreateShaderResourceView(*dxgi->device,
|
||||
*(ID3D11Resource **)teximpl->gpu, NULL,
|
||||
(ID3D11ShaderResourceView **)comRef_newGlobal(&teximpl->srv));
|
||||
}
|
||||
|
||||
// map the texture simply to get the pitch and stride
|
||||
|
@ -141,16 +114,13 @@ static bool d3d11_create(struct DXGIInterface * intf)
|
|||
goto fail;
|
||||
}
|
||||
|
||||
dxgi->pitch = mapping.RowPitch;
|
||||
dxgi->stride = mapping.RowPitch / dxgi->bpp;
|
||||
|
||||
ID3D11DeviceContext_Unmap(*dxgi->deviceContext,
|
||||
*(ID3D11Resource **)TEXIMPL(dxgi->texture[0])->cpu, 0);
|
||||
|
||||
*pitch = mapping.RowPitch;
|
||||
return true;
|
||||
|
||||
fail:
|
||||
d3d11_free();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -199,76 +169,12 @@ static void copyFrameFull(Texture * tex, ID3D11Texture2D * src)
|
|||
}
|
||||
}
|
||||
|
||||
static void copyFrameDownsampled(Texture * tex, ID3D11Texture2D * src)
|
||||
{
|
||||
struct D3D11TexImpl * teximpl = TEXIMPL(*tex);
|
||||
ID3D11Texture2D * dst = *teximpl->gpu;
|
||||
|
||||
if (tex->texDamageCount < 0)
|
||||
ID3D11DeviceContext_ResolveSubresource(*dxgi->deviceContext,
|
||||
(ID3D11Resource *)dst, 0,
|
||||
(ID3D11Resource *)src, 0,
|
||||
dxgi->dxgiFormat);
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < tex->texDamageCount; ++i)
|
||||
{
|
||||
FrameDamageRect * rect = tex->texDamageRects + i;
|
||||
D3D11_BOX box =
|
||||
{
|
||||
.left = rect->x << dxgi->downsampleLevel,
|
||||
.top = rect->y << dxgi->downsampleLevel,
|
||||
.front = 0,
|
||||
.back = 1,
|
||||
.right = (rect->x + rect->width ) << dxgi->downsampleLevel,
|
||||
.bottom = (rect->y + rect->height) << dxgi->downsampleLevel,
|
||||
};
|
||||
ID3D11DeviceContext_CopySubresourceRegion(*dxgi->deviceContext,
|
||||
(ID3D11Resource *)dst, 0, box.left, box.top, 0,
|
||||
(ID3D11Resource *)src, 0, &box);
|
||||
}
|
||||
}
|
||||
|
||||
ID3D11DeviceContext_GenerateMips(*dxgi->deviceContext, *teximpl->srv);
|
||||
if (tex->texDamageCount < 0)
|
||||
ID3D11DeviceContext_CopySubresourceRegion(*dxgi->deviceContext,
|
||||
*(ID3D11Resource **)teximpl->cpu, 0, 0, 0, 0,
|
||||
(ID3D11Resource * )dst , dxgi->downsampleLevel, NULL);
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < tex->texDamageCount; ++i)
|
||||
{
|
||||
FrameDamageRect * rect = tex->texDamageRects + i;
|
||||
D3D11_BOX box =
|
||||
{
|
||||
.left = rect->x,
|
||||
.top = rect->y,
|
||||
.front = 0,
|
||||
.back = 1,
|
||||
.right = rect->x + rect->width ,
|
||||
.bottom = rect->y + rect->height,
|
||||
};
|
||||
|
||||
ID3D11DeviceContext_CopySubresourceRegion(*dxgi->deviceContext,
|
||||
*(ID3D11Resource **)teximpl->cpu, 0, box.left, box.top, 0,
|
||||
(ID3D11Resource * )dst , dxgi->downsampleLevel, &box);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool d3d11_copyFrame(Texture * tex, ID3D11Texture2D * src)
|
||||
{
|
||||
struct D3D11TexImpl * teximpl = TEXIMPL(*tex);
|
||||
|
||||
INTERLOCKED_SECTION(dxgi->deviceContextLock,
|
||||
{
|
||||
tex->copyTime = microtime();
|
||||
|
||||
if (teximpl->gpu && *teximpl->gpu)
|
||||
copyFrameDownsampled(tex, src);
|
||||
else
|
||||
copyFrameFull(tex, src);
|
||||
|
||||
copyFrameFull(tex, src);
|
||||
ID3D11DeviceContext_Flush(*dxgi->deviceContext);
|
||||
});
|
||||
return true;
|
||||
|
@ -339,6 +245,7 @@ struct DXGICopyBackend copyBackendD3D11 = {
|
|||
.name = "Direct3D 11",
|
||||
.code = "d3d11",
|
||||
.create = d3d11_create,
|
||||
.configure = d3d11_configure,
|
||||
.free = d3d11_free,
|
||||
.copyFrame = d3d11_copyFrame,
|
||||
.mapTexture = d3d11_mapTexture,
|
||||
|
|
|
@ -95,8 +95,8 @@ static bool d3d12_create(struct DXGIInterface * intf)
|
|||
{
|
||||
DEBUG_WARN("The D3D12 backend does not support downsampling yet");
|
||||
dxgi->downsampleLevel = 0;
|
||||
dxgi->targetWidth = dxgi->width;
|
||||
dxgi->targetHeight = dxgi->height;
|
||||
dxgi->outputWidth = dxgi->width;
|
||||
dxgi->outputHeight = dxgi->height;
|
||||
}
|
||||
|
||||
if (dxgi->debug)
|
||||
|
|
|
@ -51,6 +51,7 @@
|
|||
|
||||
//post processers
|
||||
extern const DXGIPostProcess DXGIPP_SDRWhiteLevel;
|
||||
extern const DXGIPostProcess DXGIPP_RGB24;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
|
@ -58,6 +59,9 @@ typedef struct
|
|||
ID3D11ShaderResourceView * srv;
|
||||
const DXGIPostProcess * pp;
|
||||
void * opaque;
|
||||
|
||||
bool configured;
|
||||
int rows, cols;
|
||||
}
|
||||
PostProcessInstance;
|
||||
|
||||
|
@ -89,7 +93,10 @@ static bool dxgi_deinit(void);
|
|||
static CaptureResult dxgi_releaseFrame(void);
|
||||
|
||||
static bool ppInit(const DXGIPostProcess * pp, bool shareable);
|
||||
static ID3D11Texture2D * ppRun(Texture * tex, ID3D11Texture2D * src);
|
||||
static ID3D11Texture2D * ppRun(Texture * tex, ID3D11Texture2D * src,
|
||||
int * width, int * height,
|
||||
int * rows , int * cols,
|
||||
CaptureFormat * format);
|
||||
static void ppFreeAll(void);
|
||||
|
||||
// implementation
|
||||
|
@ -301,7 +308,7 @@ static bool initVertexShader(void)
|
|||
|
||||
// compile and create the vertex shader
|
||||
comRef_defineLocal(ID3DBlob, byteCode);
|
||||
if (!compileShader(byteCode, "main", "vs_5_0", vshaderSrc))
|
||||
if (!compileShader(byteCode, "main", "vs_5_0", vshaderSrc, NULL))
|
||||
return false;
|
||||
|
||||
comRef_defineLocal(ID3D11VertexShader, vshader);
|
||||
|
@ -530,7 +537,8 @@ static bool dxgi_init(void)
|
|||
*tmp,
|
||||
D3D_DRIVER_TYPE_UNKNOWN,
|
||||
NULL,
|
||||
D3D11_CREATE_DEVICE_VIDEO_SUPPORT,
|
||||
D3D11_CREATE_DEVICE_VIDEO_SUPPORT |
|
||||
(this->debug ? D3D11_CREATE_DEVICE_DEBUG : 0),
|
||||
featureLevels, featureLevelCount,
|
||||
D3D11_SDK_VERSION,
|
||||
(ID3D11Device **)comRef_newGlobal(&this->device),
|
||||
|
@ -729,7 +737,7 @@ static bool dxgi_init(void)
|
|||
this->hdr = this->dxgiColorSpace == DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020;
|
||||
}
|
||||
|
||||
this->bpp = 4;
|
||||
// set the initial format
|
||||
switch(this->dxgiFormat)
|
||||
{
|
||||
case DXGI_FORMAT_B8G8R8A8_UNORM:
|
||||
|
@ -740,10 +748,12 @@ static bool dxgi_init(void)
|
|||
this->format = CAPTURE_FMT_RGBA;
|
||||
break;
|
||||
|
||||
// we convert to HDR10 to save bandwidth
|
||||
case DXGI_FORMAT_R10G10B10A2_UNORM:
|
||||
this->format = CAPTURE_FMT_RGBA10;
|
||||
break;
|
||||
|
||||
case DXGI_FORMAT_R16G16B16A16_FLOAT:
|
||||
this->dxgiFormat = DXGI_FORMAT_R10G10B10A2_UNORM;
|
||||
this->format = CAPTURE_FMT_RGBA10;
|
||||
this->format = CAPTURE_FMT_RGBA16F;
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -752,8 +762,8 @@ static bool dxgi_init(void)
|
|||
}
|
||||
|
||||
this->downsampleLevel = 0;
|
||||
this->targetWidth = this->width;
|
||||
this->targetHeight = this->height;
|
||||
this->outputWidth = this->width;
|
||||
this->outputHeight = this->height;
|
||||
|
||||
DownsampleRule * rule, * match = NULL;
|
||||
vector_forEachRef(rule, &downsampleRules)
|
||||
|
@ -770,11 +780,11 @@ static bool dxgi_init(void)
|
|||
{
|
||||
DEBUG_INFO("Matched downsample rule %d", rule->id);
|
||||
this->downsampleLevel = match->level;
|
||||
this->targetWidth >>= match->level;
|
||||
this->targetHeight >>= match->level;
|
||||
this->outputWidth >>= match->level;
|
||||
this->outputHeight >>= match->level;
|
||||
}
|
||||
|
||||
DEBUG_INFO("Request Size : %u x %u", this->targetWidth, this->targetHeight);
|
||||
DEBUG_INFO("Request Size : %u x %u", this->outputWidth, this->outputHeight);
|
||||
|
||||
const char * copyBackend = option_get_string("dxgi", "copyBackend");
|
||||
for (int i = 0; i < ARRAY_LENGTH(backends); ++i)
|
||||
|
@ -792,7 +802,7 @@ static bool dxgi_init(void)
|
|||
}
|
||||
}
|
||||
|
||||
DEBUG_INFO("Output Size : %u x %u", this->targetWidth, this->targetHeight);
|
||||
DEBUG_INFO("Output Size : %u x %u", this->outputWidth, this->outputHeight);
|
||||
|
||||
if (!this->backend)
|
||||
{
|
||||
|
@ -812,23 +822,21 @@ static bool dxgi_init(void)
|
|||
if (!initVertexShader())
|
||||
goto fail;
|
||||
|
||||
const D3D11_VIEWPORT vp =
|
||||
{
|
||||
.TopLeftX = 0.0f,
|
||||
.TopLeftY = 0.0f,
|
||||
.Width = this->width,
|
||||
.Height = this->height,
|
||||
.MinDepth = 0.0f,
|
||||
.MaxDepth = 1.0f,
|
||||
};
|
||||
ID3D11DeviceContext_RSSetViewports(*this->deviceContext, 1, &vp);
|
||||
|
||||
// if HDR add the SDRWhiteLevel post processor to correct the output
|
||||
if (this->hdr && !ppInit(&DXGIPP_SDRWhiteLevel,
|
||||
this->backend != ©BackendD3D11))
|
||||
if (this->hdr)
|
||||
{
|
||||
DEBUG_ERROR("Failed to initialize the SDRWhiteLevel post processor");
|
||||
goto fail;
|
||||
if (!ppInit(&DXGIPP_SDRWhiteLevel, this->backend != ©BackendD3D11))
|
||||
{
|
||||
DEBUG_ERROR("Failed to initialize the SDRWhiteLevel post processor");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// only support DX11 for this atm
|
||||
if (this->backend == ©BackendD3D11)
|
||||
if (!ppInit(&DXGIPP_RGB24, false))
|
||||
DEBUG_WARN("Failed to initialize the RGB24 post processor");
|
||||
}
|
||||
|
||||
for (int i = 0; i < LGMP_Q_FRAME_LEN; ++i)
|
||||
|
@ -874,6 +882,7 @@ static bool dxgi_deinit(void)
|
|||
ppFreeAll();
|
||||
if (this->backend)
|
||||
{
|
||||
this->backendConfigured = false;
|
||||
this->backend->free();
|
||||
this->backend = NULL;
|
||||
}
|
||||
|
@ -1121,9 +1130,75 @@ static CaptureResult dxgi_capture(void)
|
|||
computeFrameDamage(tex);
|
||||
computeTexDamage(tex);
|
||||
|
||||
ID3D11Texture2D * dst = ppRun(tex, *src);
|
||||
if (dst != *src)
|
||||
ID3D11DeviceContext_Flush(*this->deviceContext);
|
||||
// run any postprocessors
|
||||
int width = this->width;
|
||||
int height = this->height;
|
||||
int cols = this->width;
|
||||
int rows = this->height;
|
||||
CaptureFormat format = this->format;
|
||||
ID3D11Texture2D *dst = ppRun(
|
||||
tex, *src, &width, &height, &cols, &rows, &format);
|
||||
|
||||
if (!this->backendConfigured)
|
||||
{
|
||||
switch(format)
|
||||
{
|
||||
case CAPTURE_FMT_RGBA:
|
||||
this->bpp = 4;
|
||||
this->dxgiFormat = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
break;
|
||||
|
||||
case CAPTURE_FMT_BGRA:
|
||||
this->bpp = 4;
|
||||
this->dxgiFormat = DXGI_FORMAT_B8G8R8A8_UNORM;
|
||||
break;
|
||||
|
||||
case CAPTURE_FMT_RGBA10:
|
||||
this->bpp = 4;
|
||||
this->dxgiFormat = DXGI_FORMAT_R10G10B10A2_UNORM;
|
||||
break;
|
||||
|
||||
case CAPTURE_FMT_RGBA16F:
|
||||
this->bpp = 8;
|
||||
this->dxgiFormat = DXGI_FORMAT_R16G16B16A16_FLOAT;
|
||||
break;
|
||||
|
||||
case CAPTURE_FMT_BGR:
|
||||
this->bpp = 4;
|
||||
this->dxgiFormat = DXGI_FORMAT_B8G8R8A8_UNORM;
|
||||
break;
|
||||
|
||||
case CAPTURE_FMT_COLOR :
|
||||
case CAPTURE_FMT_MONO :
|
||||
case CAPTURE_FMT_MASKED:
|
||||
case CAPTURE_FMT_MAX :
|
||||
DEBUG_ERROR("Unsupported input format");
|
||||
result = CAPTURE_RESULT_ERROR;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
unsigned pitch = 0;
|
||||
LG_LOCK(this->deviceContextLock);
|
||||
if (!this->backend->configure(cols, rows, this->dxgiFormat, &pitch))
|
||||
{
|
||||
LG_UNLOCK(this->deviceContextLock);
|
||||
DEBUG_ERROR("Failed to configure the copy backend");
|
||||
result = CAPTURE_RESULT_ERROR;
|
||||
goto exit;
|
||||
}
|
||||
LG_UNLOCK(this->deviceContextLock);
|
||||
|
||||
DEBUG_ASSERT(pitch && "copy backend did not return the pitch");
|
||||
|
||||
this->backendConfigured = true;
|
||||
this->outputWidth = width;
|
||||
this->outputHeight = height;
|
||||
this->outputFormat = format;
|
||||
this->dataWidth = cols;
|
||||
this->dataHeight = rows;
|
||||
this->pitch = pitch;
|
||||
this->stride = pitch / this->bpp;
|
||||
}
|
||||
|
||||
if (!this->backend->copyFrame(tex, dst))
|
||||
{
|
||||
|
@ -1265,17 +1340,19 @@ static CaptureResult dxgi_waitFrame(CaptureFrame * frame, const size_t maxFrameS
|
|||
|
||||
tex->state = TEXTURE_STATE_MAPPED;
|
||||
|
||||
const unsigned int maxHeight = maxFrameSize / this->pitch;
|
||||
const unsigned int maxRows = maxFrameSize / this->pitch;
|
||||
|
||||
frame->formatVer = tex->formatVer;
|
||||
frame->screenWidth = this->width;
|
||||
frame->screenHeight = this->height;
|
||||
frame->frameWidth = this->targetWidth;
|
||||
frame->frameHeight = min(maxHeight, this->targetHeight);
|
||||
frame->truncated = maxHeight < this->targetHeight;
|
||||
frame->dataWidth = this->dataWidth;
|
||||
frame->dataHeight = min(maxRows, this->dataHeight);
|
||||
frame->frameWidth = this->outputWidth;
|
||||
frame->frameHeight = this->outputHeight;
|
||||
frame->truncated = maxRows < this->dataHeight;
|
||||
frame->pitch = this->pitch;
|
||||
frame->stride = this->stride;
|
||||
frame->format = this->format;
|
||||
frame->format = this->outputFormat;
|
||||
frame->hdr = this->hdr;
|
||||
frame->hdrPQ = false;
|
||||
frame->rotation = this->rotation;
|
||||
|
@ -1288,8 +1365,7 @@ static CaptureResult dxgi_waitFrame(CaptureFrame * frame, const size_t maxFrameS
|
|||
return CAPTURE_RESULT_OK;
|
||||
}
|
||||
|
||||
static CaptureResult dxgi_getFrame(FrameBuffer * frame,
|
||||
const unsigned int height, int frameIndex)
|
||||
static CaptureResult dxgi_getFrame(FrameBuffer * frame, int frameIndex)
|
||||
{
|
||||
DEBUG_ASSERT(this);
|
||||
DEBUG_ASSERT(this->initialized);
|
||||
|
@ -1301,14 +1377,14 @@ static CaptureResult dxgi_getFrame(FrameBuffer * frame,
|
|||
damage->count + tex->damageRectsCount > KVMFR_MAX_DAMAGE_RECTS;
|
||||
|
||||
if (damageAll)
|
||||
framebuffer_write(frame, tex->map, this->pitch * height);
|
||||
framebuffer_write(frame, tex->map, this->pitch * this->dataHeight);
|
||||
else
|
||||
{
|
||||
memcpy(damage->rects + damage->count, tex->damageRects,
|
||||
tex->damageRectsCount * sizeof(*tex->damageRects));
|
||||
damage->count += tex->damageRectsCount;
|
||||
rectsBufferToFramebuffer(damage->rects, damage->count, this->bpp, frame,
|
||||
this->pitch, height, tex->map, this->pitch);
|
||||
this->pitch, this->dataHeight, tex->map, this->pitch);
|
||||
}
|
||||
|
||||
for (int i = 0; i < LGMP_Q_FRAME_LEN; ++i)
|
||||
|
@ -1373,22 +1449,27 @@ static CaptureResult dxgi_releaseFrame(void)
|
|||
|
||||
static bool ppInit(const DXGIPostProcess * pp, bool shareable)
|
||||
{
|
||||
if (!pp->setup(this->device, this->deviceContext, this->output))
|
||||
if (!pp->setup(this->device, this->deviceContext, this->output, shareable))
|
||||
return false;
|
||||
|
||||
for(int i = 0; i < this->maxTextures; ++i)
|
||||
{
|
||||
PostProcessInstance inst = { .pp = pp };
|
||||
if (!pp->init(&inst.opaque, this->width, this->height, shareable))
|
||||
if (!pp->init(&inst.opaque))
|
||||
{
|
||||
DEBUG_ERROR("Failed to init a post processor");
|
||||
return false;
|
||||
|
||||
}
|
||||
vector_push(&this->texture[i].pp, &inst);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static ID3D11Texture2D * ppRun(Texture * tex, ID3D11Texture2D * src)
|
||||
static ID3D11Texture2D * ppRun(Texture * tex, ID3D11Texture2D * src,
|
||||
int * width, int * height,
|
||||
int * rows, int * cols,
|
||||
CaptureFormat * format)
|
||||
{
|
||||
PostProcessInstance * inst;
|
||||
vector_forEachRef(inst, &tex->pp)
|
||||
|
@ -1419,12 +1500,42 @@ static ID3D11Texture2D * ppRun(Texture * tex, ID3D11Texture2D * src)
|
|||
if (FAILED(status))
|
||||
{
|
||||
DEBUG_WINERROR("Failed to create the source resource view", status);
|
||||
continue;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
inst->src = src;
|
||||
}
|
||||
|
||||
LG_LOCK(this->deviceContextLock);
|
||||
if (!inst->configured)
|
||||
{
|
||||
if (!inst->pp->configure(inst->opaque,
|
||||
width, height,
|
||||
cols , rows,
|
||||
format))
|
||||
{
|
||||
LG_UNLOCK(this->deviceContextLock);
|
||||
DEBUG_ERROR("setFormat failed on a post processor");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
inst->configured = true;
|
||||
inst->rows = *rows;
|
||||
inst->cols = *cols;
|
||||
}
|
||||
|
||||
// set the viewport
|
||||
const D3D11_VIEWPORT vp =
|
||||
{
|
||||
.TopLeftX = 0.0f,
|
||||
.TopLeftY = 0.0f,
|
||||
.Width = inst->cols,
|
||||
.Height = inst->rows,
|
||||
.MinDepth = 0.0f,
|
||||
.MaxDepth = 1.0f,
|
||||
};
|
||||
ID3D11DeviceContext_RSSetViewports(*this->deviceContext, 1, &vp);
|
||||
|
||||
// set the vertex shader
|
||||
ID3D11DeviceContext_VSSetShader(
|
||||
*this->deviceContext, *this->vshader, NULL, 0);
|
||||
|
@ -1432,9 +1543,19 @@ static ID3D11Texture2D * ppRun(Texture * tex, ID3D11Texture2D * src)
|
|||
// run the post processor
|
||||
ID3D11Texture2D * out = inst->pp->run(inst->opaque, inst->srv);
|
||||
|
||||
// if the post processor returned a different texture then draw to run it
|
||||
// if the post processor failed
|
||||
if (!out)
|
||||
{
|
||||
LG_UNLOCK(this->deviceContextLock);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// if the post processor did nothing, just continue
|
||||
if (out == src)
|
||||
{
|
||||
LG_UNLOCK(this->deviceContextLock);
|
||||
continue;
|
||||
}
|
||||
|
||||
// draw the full screen quad
|
||||
ID3D11DeviceContext_IASetPrimitiveTopology(
|
||||
|
@ -1443,6 +1564,7 @@ static ID3D11Texture2D * ppRun(Texture * tex, ID3D11Texture2D * src)
|
|||
|
||||
// the output is now the input
|
||||
src = out;
|
||||
LG_UNLOCK(this->deviceContextLock);
|
||||
}
|
||||
|
||||
return src;
|
||||
|
|
|
@ -96,19 +96,21 @@ struct DXGIInterface
|
|||
DXGI_COLOR_SPACE_TYPE dxgiColorSpace;
|
||||
ID3D11VertexShader ** vshader;
|
||||
struct DXGICopyBackend * backend;
|
||||
bool backendConfigured;
|
||||
|
||||
CaptureGetPointerBuffer getPointerBufferFn;
|
||||
CapturePostPointerBuffer postPointerBufferFn;
|
||||
LGEvent * frameEvent;
|
||||
|
||||
unsigned int formatVer;
|
||||
unsigned int width , targetWidth ;
|
||||
unsigned int height, targetHeight;
|
||||
unsigned int width , outputWidth , dataWidth;
|
||||
unsigned int height, outputHeight, dataHeight;
|
||||
unsigned int downsampleLevel;
|
||||
unsigned int pitch;
|
||||
unsigned int stride;
|
||||
unsigned int padding;
|
||||
unsigned int bpp;
|
||||
CaptureFormat format;
|
||||
CaptureFormat format, outputFormat;
|
||||
CaptureRotation rotation;
|
||||
|
||||
int lastPointerX, lastPointerY;
|
||||
|
@ -122,6 +124,8 @@ struct DXGICopyBackend
|
|||
const char * name;
|
||||
const char * code;
|
||||
bool (*create)(struct DXGIInterface * intf);
|
||||
bool (*configure)(unsigned width, unsigned height,
|
||||
DXGI_FORMAT format, unsigned * pitch);
|
||||
void (*free)(void);
|
||||
bool (*copyFrame)(Texture * tex, ID3D11Texture2D * src);
|
||||
CaptureResult (*mapTexture)(Texture * tex);
|
||||
|
|
|
@ -21,6 +21,9 @@
|
|||
#include <d3d11.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "interface/capture.h"
|
||||
#include "common/locking.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/* the friendly name of the processor for debugging */
|
||||
|
@ -33,14 +36,17 @@ typedef struct
|
|||
bool (*setup)(
|
||||
ID3D11Device ** device,
|
||||
ID3D11DeviceContext ** context,
|
||||
IDXGIOutput ** output);
|
||||
IDXGIOutput ** output,
|
||||
bool shareable);
|
||||
|
||||
/* instance initialization */
|
||||
bool (*init)(
|
||||
void ** opaque,
|
||||
int width,
|
||||
int height,
|
||||
bool shareable);
|
||||
bool (*init)(void ** opaque);
|
||||
|
||||
/* showtime configuration */
|
||||
bool (*configure)(void * opaque,
|
||||
int * width, int * height, // the image dimensions
|
||||
int * cols , int * rows , // the texture dimensions for packed data
|
||||
CaptureFormat * type);
|
||||
|
||||
/* perform the processing */
|
||||
ID3D11Texture2D * (*run)(void * opaque, ID3D11ShaderResourceView * srv);
|
||||
|
|
251
host/platform/Windows/capture/DXGI/src/pp/rgb24.c
Normal file
251
host/platform/Windows/capture/DXGI/src/pp/rgb24.c
Normal file
|
@ -0,0 +1,251 @@
|
|||
/**
|
||||
* 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 <math.h>
|
||||
|
||||
typedef struct RGB24
|
||||
{
|
||||
ID3D11Device ** device;
|
||||
ID3D11DeviceContext ** context;
|
||||
bool shareable;
|
||||
|
||||
int size;
|
||||
ID3D11PixelShader ** pshader;
|
||||
}
|
||||
RGB24;
|
||||
static RGB24 this = {0};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ID3D11Texture2D ** tex;
|
||||
ID3D11RenderTargetView ** target;
|
||||
}
|
||||
RGB24Inst;
|
||||
|
||||
|
||||
static bool rgb24_setup(
|
||||
ID3D11Device ** device,
|
||||
ID3D11DeviceContext ** context,
|
||||
IDXGIOutput ** output,
|
||||
bool shareable
|
||||
)
|
||||
{
|
||||
this.device = device;
|
||||
this.context = context;
|
||||
this.shareable = shareable;
|
||||
return true;
|
||||
}
|
||||
|
||||
static void rgb24_finish(void)
|
||||
{
|
||||
memset(&this, 0, sizeof(this));
|
||||
}
|
||||
|
||||
static bool rgb24_configure(void * opaque,
|
||||
int * width, int * height,
|
||||
int * cols , int * rows ,
|
||||
CaptureFormat * format)
|
||||
{
|
||||
RGB24Inst * inst = (RGB24Inst *)opaque;
|
||||
|
||||
HRESULT status;
|
||||
comRef_scopePush();
|
||||
|
||||
if (!this.pshader)
|
||||
{
|
||||
int pixels = (*cols * *rows) * 3 / 4;
|
||||
this.size = (((int)ceil(sqrt(pixels))) + 0x3F) & ~0x3F;
|
||||
|
||||
char sWidth[6], sHeight[6], sSize[6];
|
||||
snprintf(sWidth , sizeof(sWidth ), "%d", *width );
|
||||
snprintf(sHeight, sizeof(sHeight), "%d", *height);
|
||||
snprintf(sSize , sizeof(sSize ), "%d", this.size);
|
||||
|
||||
const D3D_SHADER_MACRO defines[] =
|
||||
{
|
||||
{"INPUT_WIDTH" , sWidth },
|
||||
{"INPUT_HEIGHT" , sHeight},
|
||||
{"OUTPUT_SIZE" , sSize },
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
static const char * pshaderSrc =
|
||||
"Texture2D<float4> gInputTexture : register(t0);\n"
|
||||
"\n"
|
||||
"float4 main(\n"
|
||||
" float4 position : SV_POSITION,\n"
|
||||
" float2 texCoord : TEXCOORD0) : SV_TARGET\n"
|
||||
"{\n"
|
||||
" uint outputIdx = uint(texCoord.y * OUTPUT_SIZE) * OUTPUT_SIZE +\n"
|
||||
" uint(texCoord.x * OUTPUT_SIZE);\n"
|
||||
"\n"
|
||||
" uint fst = (outputIdx * 4) / 3;\n"
|
||||
" float4 color0 = gInputTexture.Load(\n"
|
||||
" uint3(fst % INPUT_WIDTH, fst / INPUT_WIDTH, 0));\n"
|
||||
"\n"
|
||||
" uint snd = fst + 1;\n"
|
||||
" float4 color3 = gInputTexture.Load(\n"
|
||||
" uint3(snd % INPUT_WIDTH, snd / INPUT_WIDTH, 0));\n"
|
||||
"\n"
|
||||
" uint outputIdxMod3 = outputIdx % 3;\n"
|
||||
"\n"
|
||||
" float4 color1 = outputIdxMod3 <= 1 ? color0 : color3;\n"
|
||||
" float4 color2 = outputIdxMod3 == 0 ? color0 : color3;\n"
|
||||
"\n"
|
||||
" float b = color0.bgr[outputIdxMod3];\n"
|
||||
" float g = color1.grb[outputIdxMod3];\n"
|
||||
" float r = color2.rbg[outputIdxMod3];\n"
|
||||
" float a = color3.bgr[outputIdxMod3];\n"
|
||||
" return float4(r, g, b, a);\n"
|
||||
"}\n";
|
||||
|
||||
comRef_defineLocal(ID3DBlob, byteCode);
|
||||
if (!compileShader(byteCode, "main", "ps_5_0", pshaderSrc, defines))
|
||||
goto fail;
|
||||
|
||||
comRef_defineLocal(ID3D11PixelShader, pshader);
|
||||
HRESULT status = ID3D11Device_CreatePixelShader(
|
||||
*this.device,
|
||||
ID3D10Blob_GetBufferPointer(*byteCode),
|
||||
ID3D10Blob_GetBufferSize (*byteCode),
|
||||
NULL,
|
||||
pshader);
|
||||
|
||||
if (FAILED(status))
|
||||
{
|
||||
DEBUG_WINERROR("Failed to create the pixel shader", status);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
comRef_toGlobal(this.pshader, pshader);
|
||||
}
|
||||
|
||||
// This texture is actually going to contain the packed BGR24 output
|
||||
D3D11_TEXTURE2D_DESC texDesc =
|
||||
{
|
||||
.Width = this.size,
|
||||
.Height = this.size,
|
||||
.MipLevels = 1,
|
||||
.ArraySize = 1,
|
||||
.SampleDesc.Count = 1,
|
||||
.SampleDesc.Quality = 0,
|
||||
.Usage = D3D11_USAGE_DEFAULT,
|
||||
.Format = DXGI_FORMAT_B8G8R8A8_UNORM,
|
||||
.BindFlags = D3D11_BIND_RENDER_TARGET |
|
||||
D3D11_BIND_SHADER_RESOURCE,
|
||||
.CPUAccessFlags = 0,
|
||||
.MiscFlags = 0
|
||||
};
|
||||
|
||||
// allow texture sharing with other backends
|
||||
if (this.shareable)
|
||||
texDesc.MiscFlags |=
|
||||
D3D11_RESOURCE_MISC_SHARED |
|
||||
D3D11_RESOURCE_MISC_SHARED_NTHANDLE;
|
||||
|
||||
comRef_defineLocal(ID3D11Texture2D, tex);
|
||||
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;
|
||||
}
|
||||
|
||||
*cols = this.size;
|
||||
*rows = this.size;
|
||||
*format = CAPTURE_FMT_BGR;
|
||||
|
||||
comRef_toGlobal(inst->tex , tex );
|
||||
comRef_toGlobal(inst->target, target );
|
||||
|
||||
comRef_scopePop();
|
||||
return true;
|
||||
|
||||
fail:
|
||||
comRef_scopePop();
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool rgb24_init(void ** opaque)
|
||||
{
|
||||
RGB24Inst * inst = (RGB24Inst *)calloc(1, sizeof(*inst));
|
||||
if (!inst)
|
||||
{
|
||||
DEBUG_ERROR("Failed to allocate memory");
|
||||
return false;
|
||||
}
|
||||
|
||||
*opaque = inst;
|
||||
return true;
|
||||
}
|
||||
|
||||
static void rgb24_free(void * opaque)
|
||||
{
|
||||
RGB24Inst * inst = (RGB24Inst *)opaque;
|
||||
comRef_release(inst->target);
|
||||
comRef_release(inst->tex );
|
||||
free(inst);
|
||||
}
|
||||
|
||||
static ID3D11Texture2D * rgb24_run(void * opaque,
|
||||
ID3D11ShaderResourceView * srv)
|
||||
{
|
||||
RGB24Inst * inst = (RGB24Inst *)opaque;
|
||||
|
||||
// set the pixel shader & resources
|
||||
ID3D11DeviceContext_PSSetShader(*this.context, *this.pshader, NULL, 0);
|
||||
ID3D11DeviceContext_PSSetShaderResources(*this.context, 0, 1, &srv);
|
||||
|
||||
// set the render target
|
||||
ID3D11DeviceContext_OMSetRenderTargets(*this.context, 1, inst->target, NULL);
|
||||
|
||||
return *inst->tex;
|
||||
}
|
||||
|
||||
DXGIPostProcess DXGIPP_RGB24 =
|
||||
{
|
||||
.name = "RGB24",
|
||||
.earlyInit = NULL,
|
||||
.setup = rgb24_setup,
|
||||
.init = rgb24_init,
|
||||
.free = rgb24_free,
|
||||
.configure = rgb24_configure,
|
||||
.run = rgb24_run,
|
||||
.finish = rgb24_finish
|
||||
};
|
|
@ -32,6 +32,7 @@ typedef struct SDRWhiteLevel
|
|||
ID3D11Device ** device;
|
||||
ID3D11DeviceContext ** context;
|
||||
|
||||
bool shareable;
|
||||
ID3D11PixelShader ** pshader;
|
||||
ID3D11SamplerState ** sampler;
|
||||
ID3D11Buffer ** buffer;
|
||||
|
@ -40,7 +41,7 @@ typedef struct SDRWhiteLevel
|
|||
float sdrWhiteLevel;
|
||||
}
|
||||
SDRWhiteLevel;
|
||||
SDRWhiteLevel this = {0};
|
||||
static SDRWhiteLevel this = {0};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
|
@ -60,15 +61,17 @@ static void updateConsts(void);
|
|||
static bool sdrWhiteLevel_setup(
|
||||
ID3D11Device ** device,
|
||||
ID3D11DeviceContext ** context,
|
||||
IDXGIOutput ** output
|
||||
IDXGIOutput ** output,
|
||||
bool shareable
|
||||
)
|
||||
{
|
||||
bool result = false;
|
||||
comRef_scopePush();
|
||||
HRESULT status;
|
||||
|
||||
this.device = device;
|
||||
this.context = context;
|
||||
this.device = device;
|
||||
this.context = context;
|
||||
this.shareable = shareable;
|
||||
|
||||
comRef_defineLocal(IDXGIOutput6, output6);
|
||||
status = IDXGIOutput_QueryInterface(
|
||||
|
@ -106,7 +109,7 @@ static bool sdrWhiteLevel_setup(
|
|||
"}\n";
|
||||
|
||||
comRef_defineLocal(ID3DBlob, byteCode);
|
||||
if (!compileShader(byteCode, "main", "ps_5_0", pshaderSrc))
|
||||
if (!compileShader(byteCode, "main", "ps_5_0", pshaderSrc, NULL))
|
||||
goto exit;
|
||||
|
||||
comRef_defineLocal(ID3D11PixelShader, pshader);
|
||||
|
@ -178,11 +181,7 @@ static void sdrWhiteLevel_finish(void)
|
|||
memset(&this, 0, sizeof(this));
|
||||
}
|
||||
|
||||
static bool sdrWhiteLevel_init(
|
||||
void ** opaque,
|
||||
int width,
|
||||
int height,
|
||||
bool shareable)
|
||||
static bool sdrWhiteLevel_init(void ** opaque)
|
||||
{
|
||||
SDRWhiteLevelInst * inst = (SDRWhiteLevelInst *)calloc(1, sizeof(*inst));
|
||||
if (!inst)
|
||||
|
@ -191,13 +190,48 @@ static bool sdrWhiteLevel_init(
|
|||
return false;
|
||||
}
|
||||
|
||||
*opaque = inst;
|
||||
return true;
|
||||
}
|
||||
|
||||
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 bool sdrWhiteLevel_configure(void * opaque,
|
||||
int * width, int * height,
|
||||
int * cols , int * rows,
|
||||
CaptureFormat * format)
|
||||
{
|
||||
SDRWhiteLevelInst * inst = (SDRWhiteLevelInst *)opaque;
|
||||
if (inst->tex)
|
||||
return true;
|
||||
|
||||
comRef_scopePush();
|
||||
|
||||
// create the output texture
|
||||
D3D11_TEXTURE2D_DESC texDesc =
|
||||
{
|
||||
.Width = width,
|
||||
.Height = height,
|
||||
.Width = *width,
|
||||
.Height = *height,
|
||||
.MipLevels = 1,
|
||||
.ArraySize = 1,
|
||||
.SampleDesc.Count = 1,
|
||||
|
@ -211,7 +245,7 @@ static bool sdrWhiteLevel_init(
|
|||
};
|
||||
|
||||
// allow texture sharing with other backends
|
||||
if (shareable)
|
||||
if (this.shareable)
|
||||
texDesc.MiscFlags |=
|
||||
D3D11_RESOURCE_MISC_SHARED |
|
||||
D3D11_RESOURCE_MISC_SHARED_NTHANDLE;
|
||||
|
@ -236,41 +270,19 @@ static bool sdrWhiteLevel_init(
|
|||
goto fail;
|
||||
}
|
||||
|
||||
*opaque = inst;
|
||||
comRef_toGlobal(inst->tex , tex );
|
||||
comRef_toGlobal(inst->target, target);
|
||||
|
||||
comRef_scopePop();
|
||||
|
||||
*format = CAPTURE_FMT_RGBA10;
|
||||
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,
|
||||
ID3D11ShaderResourceView * srv)
|
||||
{
|
||||
|
@ -299,6 +311,7 @@ DXGIPostProcess DXGIPP_SDRWhiteLevel =
|
|||
.setup = sdrWhiteLevel_setup,
|
||||
.init = sdrWhiteLevel_init,
|
||||
.free = sdrWhiteLevel_free,
|
||||
.configure = sdrWhiteLevel_configure,
|
||||
.run = sdrWhiteLevel_run,
|
||||
.finish = sdrWhiteLevel_finish
|
||||
};
|
||||
|
|
|
@ -196,18 +196,18 @@ const char * getDXGIColorSpaceTypeStr(DXGI_COLOR_SPACE_TYPE type)
|
|||
}
|
||||
|
||||
bool compileShader(ID3DBlob ** dst, const char * entry, const char * target,
|
||||
const char * code)
|
||||
const char * code, const D3D_SHADER_MACRO * defines)
|
||||
{
|
||||
ID3DBlob * errors;
|
||||
HRESULT status = D3DCompile(
|
||||
code,
|
||||
strlen(code),
|
||||
NULL,
|
||||
NULL,
|
||||
defines,
|
||||
NULL,
|
||||
entry,
|
||||
target,
|
||||
D3DCOMPILE_DEBUG | D3DCOMPILE_SKIP_OPTIMIZATION,
|
||||
0,//D3DCOMPILE_DEBUG | D3DCOMPILE_SKIP_OPTIMIZATION,
|
||||
0,
|
||||
dst,
|
||||
&errors);
|
||||
|
|
|
@ -25,7 +25,7 @@ const char * getDXGIFormatStr(DXGI_FORMAT format);
|
|||
const char * getDXGIColorSpaceTypeStr(DXGI_COLOR_SPACE_TYPE type);
|
||||
|
||||
bool compileShader(ID3DBlob ** dst, const char * entry, const char * target,
|
||||
const char * code);
|
||||
const char * code, const D3D_SHADER_MACRO * defines);
|
||||
|
||||
bool getDisplayPathInfo(HMONITOR monitor, DISPLAYCONFIG_PATH_INFO * info);
|
||||
|
||||
|
|
|
@ -75,6 +75,7 @@ struct iface
|
|||
|
||||
unsigned int maxWidth , maxHeight;
|
||||
unsigned int width , height;
|
||||
unsigned int frameHeight;
|
||||
bool resChanged, scale;
|
||||
unsigned int targetWidth, targetHeight;
|
||||
|
||||
|
@ -744,12 +745,15 @@ static CaptureResult nvfbc_waitFrame(CaptureFrame * frame,
|
|||
}
|
||||
|
||||
const unsigned int maxHeight = maxFrameSize / (this->shmStride * 4);
|
||||
this->frameHeight = min(maxHeight, this->grabHeight);
|
||||
|
||||
frame->formatVer = this->formatVer;
|
||||
frame->screenWidth = this->width;
|
||||
frame->screenHeight = this->height;
|
||||
frame->dataWidth = this->width;
|
||||
frame->dataHeight = this->height;
|
||||
frame->frameWidth = this->grabWidth;
|
||||
frame->frameHeight = min(maxHeight, this->grabHeight);
|
||||
frame->frameHeight = this->frameHeight;
|
||||
frame->truncated = maxHeight < this->grabHeight;
|
||||
frame->pitch = this->shmStride * 4;
|
||||
frame->stride = this->shmStride;
|
||||
|
@ -764,8 +768,7 @@ static CaptureResult nvfbc_waitFrame(CaptureFrame * frame,
|
|||
return CAPTURE_RESULT_OK;
|
||||
}
|
||||
|
||||
static CaptureResult nvfbc_getFrame(FrameBuffer * frame,
|
||||
const unsigned int height, int frameIndex)
|
||||
static CaptureResult nvfbc_getFrame(FrameBuffer * frame, int frameIndex)
|
||||
{
|
||||
const unsigned int h = DIFF_MAP_DIM(this->grabHeight, this->diffShift);
|
||||
const unsigned int w = DIFF_MAP_DIM(this->grabWidth, this->diffShift);
|
||||
|
@ -779,7 +782,8 @@ static CaptureResult nvfbc_getFrame(FrameBuffer * frame,
|
|||
for (unsigned int y = 0; y < h; ++y)
|
||||
{
|
||||
const unsigned int ystart = y << this->diffShift;
|
||||
const unsigned int yend = min(height, (y + 1) << this->diffShift);
|
||||
const unsigned int yend = min(this->frameHeight, (y + 1)
|
||||
<< this->diffShift);
|
||||
|
||||
for (unsigned int x = 0; x < w; )
|
||||
{
|
||||
|
@ -804,9 +808,9 @@ static CaptureResult nvfbc_getFrame(FrameBuffer * frame,
|
|||
}
|
||||
else if (this->grabStride != this->shmStride)
|
||||
{
|
||||
for (int y = 0; y < height; y += 64)
|
||||
for (int y = 0; y < this->frameHeight; y += 64)
|
||||
{
|
||||
int yend = min(height, y + 128);
|
||||
int yend = min(this->frameHeight, y + 128);
|
||||
rectCopyUnaligned(frameData, this->frameBuffer, y, yend, 0, this->shmStride * 4,
|
||||
this->grabStride * 4, this->grabWidth * 4);
|
||||
framebuffer_set_write_ptr(frame, yend * this->shmStride * 4);
|
||||
|
@ -816,7 +820,7 @@ static CaptureResult nvfbc_getFrame(FrameBuffer * frame,
|
|||
framebuffer_write(
|
||||
frame,
|
||||
this->frameBuffer,
|
||||
height * this->grabInfo.dwBufferWidth * 4
|
||||
this->frameHeight * this->grabInfo.dwBufferWidth * 4
|
||||
);
|
||||
|
||||
for (int i = 0; i < LGMP_Q_FRAME_LEN; ++i)
|
||||
|
|
|
@ -250,8 +250,13 @@ static bool sendFrame(void)
|
|||
|
||||
switch(frame.format)
|
||||
{
|
||||
case CAPTURE_FMT_BGRA : fi->type = FRAME_TYPE_BGRA ; break;
|
||||
case CAPTURE_FMT_RGBA : fi->type = FRAME_TYPE_RGBA ; break;
|
||||
case CAPTURE_FMT_BGRA:
|
||||
fi->type = FRAME_TYPE_BGRA;
|
||||
break;
|
||||
|
||||
case CAPTURE_FMT_RGBA:
|
||||
fi->type = FRAME_TYPE_RGBA;
|
||||
break;
|
||||
|
||||
case CAPTURE_FMT_RGBA10:
|
||||
fi->type = FRAME_TYPE_RGBA10;
|
||||
|
@ -262,6 +267,10 @@ static bool sendFrame(void)
|
|||
flags |= FRAME_FLAG_HDR;
|
||||
break;
|
||||
|
||||
case CAPTURE_FMT_BGR:
|
||||
fi->type = FRAME_TYPE_BGR;
|
||||
break;
|
||||
|
||||
default:
|
||||
DEBUG_ERROR("Unsupported frame format %d, skipping frame", frame.format);
|
||||
return true;
|
||||
|
@ -292,6 +301,8 @@ static bool sendFrame(void)
|
|||
fi->frameSerial = app.frameSerial++;
|
||||
fi->screenWidth = frame.screenWidth;
|
||||
fi->screenHeight = frame.screenHeight;
|
||||
fi->dataWidth = frame.dataWidth;
|
||||
fi->dataHeight = frame.dataHeight;
|
||||
fi->frameWidth = frame.frameWidth;
|
||||
fi->frameHeight = frame.frameHeight;
|
||||
fi->stride = frame.stride;
|
||||
|
@ -317,7 +328,7 @@ static bool sendFrame(void)
|
|||
return true;
|
||||
}
|
||||
|
||||
app.iface->getFrame(fb, frame.frameHeight, app.frameIndex);
|
||||
app.iface->getFrame(fb, app.frameIndex);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue