Separate out the actual screenshot comparison.

Fixes #109.
This commit is contained in:
Unknown W. Brackets committed 2013-02-08 00:25:29 -08:00
1 parent b24d41b156
commit 6a72b0d325
7 files changed
+128 -39

No files matched your search

+5 -1
View File
@@ -918,7 +918,11 @@ if(WIN32)
endif()
if(HEADLESS)
add_executable(PPSSPPHeadless headless/Headless.cpp headless/StubHost.h)
add_executable(PPSSPPHeadless
headless/Headless.cpp
headless/StubHost.h
headless/Compare.cpp
headless/Compare.h)
target_link_libraries(PPSSPPHeadless ${CoreLibName}
${COCOA_LIBRARY} ${CMAKE_THREAD_LIBS_INIT})
setup_target_project(PPSSPPHeadless headless)
+77
View File
@@ -0,0 +1,77 @@
// Copyright (c) 2012- PPSSPP Project.
// 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, version 2.0 or later versions.
// 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 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official git repository and contact information can be found at
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
#include "Compare.h"
#include "FileUtil.h"
#include <math.h>
bool CompareOutput(const std::string bootFilename)
{
std::string expect_filename = bootFilename.substr(bootFilename.length() - 4) + ".expected";
if (File::Exists(expect_filename))
{
// TODO: Do the compare here
return true;
}
else
{
fprintf(stderr, "Expectation file %s not found", expect_filename.c_str());
return false;
}
}
inline int ComparePixel(u32 pix1, u32 pix2)
{
// For now, if they're different at all except alpha, it's an error.
if ((pix1 & 0xFFFFFF) != (pix2 & 0xFFFFFF))
return 1;
return 0;
}
double CompareScreenshot(const u8 *pixels, int w, int h, int stride, const std::string screenshotFilename, std::string &error)
{
u32 *pixels32 = (u32 *) pixels;
// We assume the bitmap is the specified size, not including whatever stride.
u32 *reference = (u32 *) calloc(w * h, sizeof(u32));
FILE *bmp = fopen(screenshotFilename.c_str(), "rb");
if (bmp)
{
// The bitmap header is 14 + 40 bytes. We could validate it but the test would fail either way.
fseek(bmp, 14 + 40, SEEK_SET);
fread(reference, sizeof(u32), w * h, bmp);
fclose(bmp);
}
else
{
error = "Unable to read screenshot: " + screenshotFilename;
free(reference);
return -1.0f;
}
u32 errors = 0;
for (int y = 0; y < h; ++y)
{
for (int x = 0; x < w; ++x)
errors += ComparePixel(pixels32[y * stride + x], reference[y * w + x]);
}
free(reference);
return (double) errors / (double) (w * h);
}
+23
View File
@@ -0,0 +1,23 @@
// Copyright (c) 2012- PPSSPP Project.
// 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, version 2.0 or later versions.
// 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 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official git repository and contact information can be found at
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
#include <string>
#include "Globals.h"
bool CompareOutput(std::string bootFilename);
double CompareScreenshot(const u8 *pixels, int w, int h, int stride, const std::string screenshotFilename, std::string &error);
+2 -11
View File
@@ -13,6 +13,7 @@
#include "Log.h"
#include "LogManager.h"
#include "Compare.h"
#include "StubHost.h"
#ifdef _WIN32
#include "WindowsHeadlessHost.h"
@@ -204,17 +205,7 @@ int main(int argc, const char* argv[])
headlessHost = NULL;
if (autoCompare)
{
std::string expect_filename = std::string(bootFilename).substr(strlen(bootFilename - 4)) + ".expected";
if (File::Exists(expect_filename))
{
// TODO: Do the compare here
}
else
{
fprintf(stderr, "Expectation file %s not found", expect_filename.c_str());
}
}
CompareOutput(bootFilename);
return 0;
}
+2
View File
@@ -145,6 +145,7 @@
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\native\ext\glew\glew.c" />
<ClCompile Include="Compare.cpp" />
<ClCompile Include="Headless.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
@@ -177,6 +178,7 @@
</ProjectReference>
</ItemGroup>
<ItemGroup>
<ClInclude Include="Compare.h" />
<ClInclude Include="StubHost.h" />
<ClInclude Include="WindowsHeadlessHost.h" />
</ItemGroup>
+2
View File
@@ -4,6 +4,7 @@
<ClCompile Include="Headless.cpp" />
<ClCompile Include="..\native\ext\glew\glew.c" />
<ClCompile Include="WindowsHeadlessHost.cpp" />
<ClCompile Include="Compare.cpp" />
</ItemGroup>
<ItemGroup>
<None Include="headless.txt" />
@@ -11,5 +12,6 @@
<ItemGroup>
<ClInclude Include="StubHost.h" />
<ClInclude Include="WindowsHeadlessHost.h" />
<ClInclude Include="Compare.h" />
</ItemGroup>
</Project>
+17 -27
View File
@@ -16,6 +16,7 @@
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
#include "WindowsHeadlessHost.h"
#include "Compare.h"
#include <stdio.h>
#include <windows.h>
@@ -94,44 +95,34 @@ void WindowsHeadlessHost::SendDebugScreenshot(const u8 *pixbuf, u32 w, u32 h)
// We ignore the current framebuffer parameters and just grab the full screen.
const static int FRAME_WIDTH = 512;
const static int FRAME_HEIGHT = 272;
u32 *pixels = (u32 *) calloc(FRAME_WIDTH * FRAME_HEIGHT, sizeof(u32));
u32 *reference = (u32 *) calloc(FRAME_WIDTH * FRAME_HEIGHT, sizeof(u32));
u8 *pixels = new u8[FRAME_WIDTH * FRAME_HEIGHT * 4];
// TODO: Maybe the GPU should do this?
glReadBuffer(GL_FRONT);
glReadPixels(0, 0, FRAME_WIDTH, FRAME_HEIGHT, GL_BGRA, GL_UNSIGNED_BYTE, pixels);
BITMAPFILEHEADER header;
BITMAPINFOHEADER infoHeader;
FILE *bmp = fopen(comparisonScreenshot.c_str(), "rb");
if (bmp)
{
fread(&header, sizeof(header), 1, bmp);
fread(&infoHeader, sizeof(infoHeader), 1, bmp);
fread(reference, sizeof(u32), FRAME_WIDTH * FRAME_HEIGHT, bmp);
fclose(bmp);
}
else
fprintf_s(out, "Unable to read screenshot: %s\n", comparisonScreenshot.c_str());
std::string error;
double errors = CompareScreenshot(pixels, FRAME_WIDTH, FRAME_HEIGHT, FRAME_WIDTH, comparisonScreenshot, error);
if (errors < 0)
fprintf_s(out, "%s\n", error.c_str());
// TODO: Better error rate and move to headless/shared between platforms.
int errors = 0;
for (int i = 0; i < FRAME_WIDTH * FRAME_HEIGHT; ++i)
if (errors > 0)
{
// Ignore alpha.
// TODO: Error threshold?
errors += (pixels[i] & 0xFFFFFF) != (reference[i] & 0xFFFFFF) ? 1 : 0;
}
fprintf_s(out, "Screenshot error: %f%%\n", errors * 100.0f);
if (errors != 0)
{
fprintf_s(out, "Screenshot error: %f%%\n", (float) errors * 100.0f / (float) (FRAME_WIDTH * FRAME_HEIGHT));
// Lazy, just read in the original header to output the failed screenshot.
u8 header[14 + 40] = {0};
FILE *bmp = fopen(comparisonScreenshot.c_str(), "rb");
if (bmp)
{
fread(&header, sizeof(header), 1, bmp);
fclose(bmp);
}
FILE *saved = fopen("__testfailure.bmp", "wb");
if (saved)
{
fwrite(&header, sizeof(header), 1, saved);
fwrite(&infoHeader, sizeof(infoHeader), 1, saved);
fwrite(pixels, sizeof(u32), FRAME_WIDTH * FRAME_HEIGHT, saved);
fclose(saved);
@@ -139,8 +130,7 @@ void WindowsHeadlessHost::SendDebugScreenshot(const u8 *pixbuf, u32 w, u32 h)
}
}
free(pixels);
free(reference);
delete [] pixels;
}
void WindowsHeadlessHost::SetComparisonScreenshot(const std::string &filename)