Files
LookingGlass/idd/LGIdd/postprocess/D12FrameFormat.cpp
2026-08-13 21:41:45 +10:00

163 lines
5.9 KiB
C++

/**
* Looking Glass
* Copyright © 2017-2026 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 "postprocess/D12FrameFormat.h"
#include <cstring>
namespace
{
bool NearlyEqual(float a, float b, float tolerance)
{
const float delta = a - b;
return delta >= -tolerance && delta <= tolerance;
}
bool Identity(const D12ColorTransform& transform)
{
static const float matrixTolerance = 1.0f / 1048576.0f;
static const float lutTolerance = 1.0f / 65535.0f;
if (transform.matrixEnabled)
{
for (unsigned row = 0; row < 3; ++row)
for (unsigned column = 0; column < 4; ++column)
{
const float expected = row == column ? 1.0f : 0.0f;
const float effective =
transform.matrix[row][column] * transform.scalar;
if (!NearlyEqual(effective, expected, matrixTolerance))
return false;
}
}
if (transform.lutEnabled)
for (unsigned i = 0; i < 4096; ++i)
{
const float expected = static_cast<float>(i) / 4095.0f;
if (!NearlyEqual(transform.lut[i][0], expected, lutTolerance) ||
!NearlyEqual(transform.lut[i][1], expected, lutTolerance) ||
!NearlyEqual(transform.lut[i][2], expected, lutTolerance))
return false;
}
return true;
}
}
std::shared_ptr<const D12ColorTransform> D12::Transform(
const std::shared_ptr<const D12ColorTransform>& transform)
{
if (!transform || (!transform->matrixEnabled && !transform->lutEnabled) ||
Identity(*transform))
return nullptr;
return transform;
}
FrameType D12::Type(DXGI_FORMAT format)
{
switch (format)
{
case DXGI_FORMAT_B8G8R8A8_UNORM:
return FRAME_TYPE_BGRA;
case DXGI_FORMAT_R8G8B8A8_UNORM:
return FRAME_TYPE_RGBA;
case DXGI_FORMAT_R10G10B10A2_UNORM:
return FRAME_TYPE_RGBA10;
case DXGI_FORMAT_R16G16B16A16_FLOAT:
return FRAME_TYPE_RGBA16F;
default:
return FRAME_TYPE_INVALID;
}
}
void D12::CopyHdr(D12FrameFormat& dst, const D12FrameFormat& src)
{
dst.hdrMetadata = src.hdrMetadata;
dst.sdrWhiteLevel = src.sdrWhiteLevel;
memcpy(dst.displayPrimary, src.displayPrimary, sizeof(dst.displayPrimary));
memcpy(dst.whitePoint, src.whitePoint, sizeof(dst.whitePoint));
dst.maxDisplayLuminance = src.maxDisplayLuminance;
dst.minDisplayLuminance = src.minDisplayLuminance;
dst.maxContentLightLevel = src.maxContentLightLevel;
dst.maxFrameAverageLightLevel = src.maxFrameAverageLightLevel;
}
bool D12::Same(const D3D12_RESOURCE_DESC& left,
const D3D12_RESOURCE_DESC& right, DescCmp cmp)
{
const bool alignment = cmp != DescCmp::CREATE &&
cmp != DescCmp::COPY && cmp != DescCmp::VIEW;
const bool layout = cmp != DescCmp::COPY;
const bool flags = cmp != DescCmp::COPY &&
cmp != DescCmp::NO_FLAGS && cmp != DescCmp::VIEW;
return
left.Dimension == right.Dimension &&
(!alignment || left.Alignment == right.Alignment) &&
left.Width == right.Width &&
left.Height == right.Height &&
left.DepthOrArraySize == right.DepthOrArraySize &&
left.MipLevels == right.MipLevels &&
left.Format == right.Format &&
left.SampleDesc.Count == right.SampleDesc.Count &&
left.SampleDesc.Quality == right.SampleDesc.Quality &&
(!layout || left.Layout == right.Layout) &&
(!flags || left.Flags == right.Flags);
}
bool D12::Same(const D12FrameFormat& left, const D12FrameFormat& right,
FormatCmp cmp)
{
const DescCmp descCmp = cmp == FormatCmp::IMAGE ? DescCmp::CREATE :
(cmp == FormatCmp::NO_FLAGS ? DescCmp::NO_FLAGS : DescCmp::EXACT);
if (!Same(left.desc, right.desc, descCmp))
return false;
if (cmp == FormatCmp::IMAGE)
return
left.width == right.width &&
left.height == right.height &&
left.format == right.format &&
left.hdr == right.hdr &&
left.hdrPQ == right.hdrPQ;
return
left.dataWidth == right.dataWidth &&
left.dataHeight == right.dataHeight &&
left.pitch == right.pitch &&
left.width == right.width &&
left.height == right.height &&
left.format == right.format &&
left.hdr == right.hdr &&
left.hdrPQ == right.hdrPQ &&
left.hdrMetadata == right.hdrMetadata &&
left.sdrWhiteLevel == right.sdrWhiteLevel &&
left.colorTransform == right.colorTransform &&
memcmp(left.displayPrimary, right.displayPrimary,
sizeof(left.displayPrimary)) == 0 &&
memcmp(left.whitePoint, right.whitePoint,
sizeof(left.whitePoint)) == 0 &&
left.maxDisplayLuminance == right.maxDisplayLuminance &&
left.minDisplayLuminance == right.minDisplayLuminance &&
left.maxContentLightLevel == right.maxContentLightLevel &&
left.maxFrameAverageLightLevel == right.maxFrameAverageLightLevel;
}