port from perforce
This commit is contained in:
284
hgplus/bliss/Engine/analysis.h
Normal file
284
hgplus/bliss/Engine/analysis.h
Normal file
@@ -0,0 +1,284 @@
|
||||
#pragma bss_seg(".analysisbss")
|
||||
static ID3D11Texture2D* resolvedTexture;
|
||||
static ID3D11Texture2D* stagingTexture;
|
||||
static D3D11_MAPPED_SUBRESOURCE analysisResource;
|
||||
static int* pixels;
|
||||
static HBITMAP hbmp;
|
||||
static HDC hdcMem;
|
||||
static HDC hdc;
|
||||
static D3D11_TEXTURE2D_DESC stagingDesc;
|
||||
static unsigned int hR[256];
|
||||
static unsigned int hG[256];
|
||||
static unsigned int hB[256];
|
||||
static unsigned int waveForm[screenWidth * 256];
|
||||
static unsigned int paradeR[screenWidth * 256];
|
||||
static unsigned int paradeG[screenWidth * 256];
|
||||
static unsigned int paradeB[screenWidth * 256];
|
||||
static unsigned int vectorScope[256 * 256];
|
||||
|
||||
#pragma data_seg(".analysisdata")
|
||||
extern ID3D11Texture2D* backBufferPtr;
|
||||
extern ID3D11Device* device;
|
||||
extern ID3D11DeviceContext* deviceContext;
|
||||
|
||||
float fast_log2(float val)
|
||||
{
|
||||
int * const exp_ptr = reinterpret_cast <int *> (&val);
|
||||
int x = *exp_ptr;
|
||||
const int log_2 = ((x >> 23) & 255) - 128;
|
||||
x &= ~(255 << 23);
|
||||
x += 127 << 23;
|
||||
*exp_ptr = x;
|
||||
|
||||
return (val + log_2);
|
||||
}
|
||||
|
||||
void InitAnalysis(HWND hwnd)
|
||||
{
|
||||
backBufferPtr->GetDesc(&stagingDesc);
|
||||
stagingDesc.Usage = D3D11_USAGE_DEFAULT;
|
||||
stagingDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
stagingDesc.BindFlags = 0;
|
||||
stagingDesc.SampleDesc.Count = 1;
|
||||
device->CreateTexture2D(&stagingDesc, NULL, &resolvedTexture);
|
||||
|
||||
stagingDesc.Usage = D3D11_USAGE_STAGING;
|
||||
stagingDesc.CPUAccessFlags |= D3D11_CPU_ACCESS_READ;
|
||||
device->CreateTexture2D(&stagingDesc, NULL, &stagingTexture);
|
||||
|
||||
BITMAPINFO bmi;
|
||||
bmi.bmiHeader.biSize = sizeof(BITMAPINFO);
|
||||
bmi.bmiHeader.biWidth = 1024;
|
||||
bmi.bmiHeader.biHeight = -512; // Order pixels from top to bottom
|
||||
bmi.bmiHeader.biPlanes = 1;
|
||||
bmi.bmiHeader.biBitCount = 32; // last byte not used, 32 bit for alignment
|
||||
bmi.bmiHeader.biCompression = BI_RGB;
|
||||
bmi.bmiHeader.biSizeImage = 0;
|
||||
bmi.bmiHeader.biXPelsPerMeter = 0;
|
||||
bmi.bmiHeader.biYPelsPerMeter = 0;
|
||||
bmi.bmiHeader.biClrUsed = 0;
|
||||
bmi.bmiHeader.biClrImportant = 0;
|
||||
bmi.bmiColors[0].rgbBlue = 0;
|
||||
bmi.bmiColors[0].rgbGreen = 0;
|
||||
bmi.bmiColors[0].rgbRed = 0;
|
||||
bmi.bmiColors[0].rgbReserved = 0;
|
||||
|
||||
hdc = ::GetDC(hwnd);
|
||||
hdcMem = CreateCompatibleDC(hdc);
|
||||
hbmp = CreateDIBSection(hdc, &bmi, DIB_RGB_COLORS, (void**)&pixels, NULL, 0);
|
||||
}
|
||||
|
||||
void Analyze()
|
||||
{
|
||||
SelectObject(hdcMem, hbmp);
|
||||
deviceContext->ResolveSubresource(resolvedTexture, 0, backBufferPtr, 0, stagingDesc.Format);
|
||||
deviceContext->CopyResource(stagingTexture, resolvedTexture);
|
||||
deviceContext->Map(stagingTexture, 0, D3D11_MAP_READ, 0, &analysisResource);
|
||||
int* image = (int*)analysisResource.pData;
|
||||
memset(pixels, 0, 1024 * 512 * 4);
|
||||
|
||||
memset(hR, 0, 256 * 4);
|
||||
memset(hG, 0, 256 * 4);
|
||||
memset(hB, 0, 256 * 4);
|
||||
memset(waveForm, 0, screenWidth * 256 * 4);
|
||||
memset(paradeR, 0, screenWidth * 256 * 4);
|
||||
memset(paradeG, 0, screenWidth * 256 * 4);
|
||||
memset(paradeB, 0, screenWidth * 256 * 4);
|
||||
memset(vectorScope, 0, 256 * 256 * 4);
|
||||
|
||||
// Gather data
|
||||
for (int y = 0; y < screenHeight; ++y)
|
||||
{
|
||||
for (int x = 0; x < screenWidth; ++x)
|
||||
{
|
||||
unsigned char* colors = (unsigned char*)&image[y * (analysisResource.RowPitch / 4) + x]; // BGRA
|
||||
float luminance = 0.2126f * colors[2] + 0.7152f * colors[1] + 0.0722f * colors[0];
|
||||
|
||||
float umax = 0.436f;
|
||||
float vmax = 0.615f;
|
||||
float ly = luminance / 255.0f;
|
||||
float fu = 0.492f * (colors[0] / 255.0f - ly);
|
||||
float fv = 0.877f * (colors[2] / 255.0f - ly);
|
||||
int u = min(255, max(0, 128 * (1 + fu / umax)));
|
||||
int v = min(255, max(0, 128 * (1 + fv / vmax)));
|
||||
|
||||
int l = (int)(luminance);
|
||||
waveForm[l * screenWidth + x]++;
|
||||
vectorScope[v * 256 + u]++;
|
||||
paradeR[colors[2] * screenWidth + x]++;
|
||||
paradeG[colors[1] * screenWidth + x]++;
|
||||
paradeB[colors[0] * screenWidth + x]++;
|
||||
hR[colors[2]]++;
|
||||
hG[colors[1]]++;
|
||||
hB[colors[0]]++;
|
||||
}
|
||||
}
|
||||
|
||||
deviceContext->Unmap(stagingTexture, 0);
|
||||
|
||||
// Determine max values
|
||||
float maxHistogramValue = 0;
|
||||
float maxVectorscopeValue = 0;
|
||||
float maxWaveForm = 0;
|
||||
float maxParadeR = 0;
|
||||
float maxParadeG = 0;
|
||||
float maxParadeB = 0;
|
||||
for (int i = 0; i < 256; ++i)
|
||||
{
|
||||
if (hR[i] > maxHistogramValue)
|
||||
maxHistogramValue = hR[i];
|
||||
if (hG[i] > maxHistogramValue)
|
||||
maxHistogramValue = hG[i];
|
||||
if (hB[i] > maxHistogramValue)
|
||||
maxHistogramValue = hB[i];
|
||||
|
||||
for (int j = 0; j < screenWidth; ++j)
|
||||
{
|
||||
if (waveForm[i * screenWidth + j] > maxWaveForm)
|
||||
maxWaveForm = waveForm[i * screenWidth + j];
|
||||
if (paradeR[i * screenWidth + j] > maxParadeR)
|
||||
maxParadeR = paradeR[i * screenWidth + j];
|
||||
if (paradeG[i * screenWidth + j] > maxParadeG)
|
||||
maxParadeG = paradeG[i * screenWidth + j];
|
||||
if (paradeB[i * screenWidth + j] > maxParadeB)
|
||||
maxParadeB = paradeB[i * screenWidth + j];
|
||||
}
|
||||
|
||||
for (int j = 0; j < 256; ++j)
|
||||
{
|
||||
if (vectorScope[i * 256 + j] > maxVectorscopeValue)
|
||||
maxVectorscopeValue = vectorScope[i * 256 + j];
|
||||
}
|
||||
}
|
||||
|
||||
maxHistogramValue = fast_log2(1 + maxHistogramValue);
|
||||
maxVectorscopeValue = fast_log2(1 + maxVectorscopeValue);
|
||||
maxWaveForm = fast_log2(1 + maxWaveForm);
|
||||
maxParadeR = fast_log2(1 + maxParadeR);
|
||||
maxParadeG = fast_log2(1 + maxParadeG);
|
||||
maxParadeB = fast_log2(1 + maxParadeB);
|
||||
|
||||
// Draw histogram
|
||||
int oldYR = 255;
|
||||
int oldYG = 255;
|
||||
int oldYB = 255;
|
||||
for (int i = 0; i < 768; ++i)
|
||||
{
|
||||
int x = i * 256 / 768;
|
||||
int yR = 255 - min(255, max(0, (int)(fast_log2(1 + hR[x]) * 256.0f / maxHistogramValue)));
|
||||
int yG = 255 - min(255, max(0, (int)(fast_log2(1 + hG[x]) * 256.0f / maxHistogramValue)));
|
||||
int yB = 255 - min(255, max(0, (int)(fast_log2(1 + hB[x]) * 256.0f / maxHistogramValue)));
|
||||
if (oldYR < yR)
|
||||
{
|
||||
for (int y = oldYR; y <= yR; ++y)
|
||||
pixels[y * 1024 + i] |= 0x000000FF;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int y = yR; y <= oldYR; ++y)
|
||||
pixels[y * 1024 + i] |= 0x000000FF;
|
||||
}
|
||||
|
||||
if (oldYG < yG)
|
||||
{
|
||||
for (int y = oldYG; y <= yG; ++y)
|
||||
pixels[y * 1024 + i] |= 0x0000FF00;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int y = yG; y <= oldYG; ++y)
|
||||
pixels[y * 1024 + i] |= 0x0000FF00;
|
||||
}
|
||||
|
||||
if (oldYB < yB)
|
||||
{
|
||||
for (int y = oldYB; y <= yB; ++y)
|
||||
pixels[y * 1024 + i] |= 0x00FF0000;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int y = yB; y <= oldYB; ++y)
|
||||
pixels[y * 1024 + i] |= 0x00FF0000;
|
||||
}
|
||||
|
||||
for (int y = yR; y <= 255; ++y)
|
||||
pixels[y * 1024 + i] |= 0x00000080;
|
||||
|
||||
for (int y = yG; y <= 255; ++y)
|
||||
pixels[y * 1024 + i] |= 0x00008000;
|
||||
|
||||
for (int y = yB; y <= 255; ++y)
|
||||
pixels[y * 1024 + i] |= 0x00800000;
|
||||
|
||||
oldYR = yR;
|
||||
oldYG = yG;
|
||||
oldYB = yB;
|
||||
}
|
||||
|
||||
for (int y = 0; y < 256; ++y)
|
||||
{
|
||||
// Draw Waveform and RGB parade
|
||||
for (int wx = 0; wx < screenWidth; ++wx)
|
||||
{
|
||||
int x = (int)(wx * 255.0f / screenWidth);
|
||||
|
||||
int luminance = (int)(fast_log2(1 + waveForm[y * screenWidth + wx]) * 256.0f / maxWaveForm);
|
||||
int r = (int)(fast_log2(1 + paradeR[y * screenWidth + wx]) * 256.0f / maxParadeR);
|
||||
int g = (int)(fast_log2(1 + paradeG[y * screenWidth + wx]) * 256.0f / maxParadeG);
|
||||
int b = (int)(fast_log2(1 + paradeB[y * screenWidth + wx]) * 256.0f / maxParadeB);
|
||||
|
||||
luminance = max(luminance, pixels[(511 - y) * 1024 + x] & 0x000000FF);
|
||||
r = max(r, pixels[(511 - y) * 1024 + x + 768]);
|
||||
g = max(g, pixels[(511 - y) * 1024 + x + 512] >> 8);
|
||||
b = max(b, pixels[(511 - y) * 1024 + x + 256] >> 16);
|
||||
|
||||
int pixel = luminance | (luminance << 8) | (luminance << 16);
|
||||
pixels[(511 - y) * 1024 + x] = pixel;
|
||||
pixels[(511 - y) * 1024 + x + 768] = r;
|
||||
pixels[(511 - y) * 1024 + x + 512] = g << 8;
|
||||
pixels[(511 - y) * 1024 + x + 256] = b << 16;
|
||||
}
|
||||
|
||||
// Draw Vectorscope
|
||||
for (int x = 0; x < 256; ++x)
|
||||
{
|
||||
float luminance = 0.1f + 0.9f * (1.0f - max(0, min(1, fast_log2(vectorScope[y * 256 + x] + 1) / maxVectorscopeValue)));
|
||||
float fx = (x - 128) / 128.0f;
|
||||
float fy = (y - 128) / 128.0f;
|
||||
if (fx*fx + fy*fy > 1)
|
||||
luminance = 0.0f;
|
||||
|
||||
float umax = 0.436f;
|
||||
float vmax = 0.615f;
|
||||
float ly = 0.5;
|
||||
float u = ((x / 128.0f) - 1.0f) * umax;
|
||||
float v = ((y / 128.0f) - 1.0f) * vmax;
|
||||
int r = luminance * 255.0f * min(1, max(0, (ly + v / 0.877f)));
|
||||
int b = luminance * 255.0f * min(1, max(0, (ly + u / 0.492f)));
|
||||
int g = luminance * 255.0f * min(1, max(0, (ly - u * 0.395f - v * 0.581f)));
|
||||
|
||||
int pixel = r | (g << 8) | (b << 16);
|
||||
pixels[(255 - y) * 1024 + x + 768] = pixel;
|
||||
}
|
||||
}
|
||||
|
||||
RECT rect = { 0 };
|
||||
|
||||
rect.left = 0;
|
||||
rect.top = 0;
|
||||
DrawText(hdcMem, "Histogram", -1, &rect, DT_SINGLELINE | DT_NOCLIP);
|
||||
|
||||
rect.left = 768;
|
||||
rect.top = 0;
|
||||
DrawText(hdcMem, "Vectorscope", -1, &rect, DT_SINGLELINE | DT_NOCLIP);
|
||||
|
||||
rect.left = 0;
|
||||
rect.top = 256;
|
||||
DrawText(hdcMem, "Waveform", -1, &rect, DT_SINGLELINE | DT_NOCLIP);
|
||||
|
||||
rect.left = 256;
|
||||
rect.top = 256;
|
||||
DrawText(hdcMem, "RGB Parade", -1, &rect, DT_SINGLELINE | DT_NOCLIP);
|
||||
|
||||
BitBlt(hdc, 0, 0, 1024, 512, hdcMem, 0, 0, SRCCOPY);
|
||||
}
|
||||
Reference in New Issue
Block a user