mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-10-01 14:58:14 +00:00
1 parent
b24d41b156
commit
6a72b0d325
7 files changed
+128
-39
No files matched your search
+5
-1
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
@@ -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)
|
||||
|
||||
Reference in new issue
Block a user