Use the debug interface to compare screenshots.

This way it's already implemented in all backends.
This commit is contained in:
Unknown W. Brackets 2014-08-30 09:45:51 -07:00
parent 5e07a40a83
commit af9e0510c3
3 changed files with 52 additions and 18 deletions

@ -18,7 +18,9 @@
#include "headless/Compare.h"
#include "file/file_util.h"
#include "Core/Host.h"
#include "GPU/Common/GPUDebugInterface.h"
#include <algorithm>
#include <cmath>
#include <cstdarg>
#include <iostream>
@ -282,18 +284,47 @@ inline int ComparePixel(u32 pix1, u32 pix2)
return 0;
}
double CompareScreenshot(const u8 *pixels, int w, int h, int stride, const std::string screenshotFilename, std::string &error)
std::vector<u32> TranslateDebugBufferToCompare(const GPUDebugBuffer *buffer, u32 stride, u32 h)
{
// If the output was small, act like everything outside was 0.
// This can happen depending on viewport parameters.
u32 safeW = std::min(stride, buffer->GetStride());
u32 safeH = std::min(h, buffer->GetHeight());
std::vector<u32> data;
data.resize(stride * h, 0);
const u32 *pixels = (const u32 *)buffer->GetData();
int outStride = buffer->GetStride();
if (!buffer->GetFlipped())
{
// Bitmaps are flipped, so we have to compare backwards in this case.
pixels += outStride * buffer->GetHeight();
outStride = -outStride;
}
u32 errors = 0;
for (u32 y = 0; y < safeH; ++y)
{
for (u32 x = 0; x < safeW; ++x)
data[y * stride + x] = pixels[x];
pixels += outStride;
}
return data;
}
double CompareScreenshot(const std::vector<u32> &pixels, u32 stride, u32 w, u32 h, 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));
u32 *reference = (u32 *) calloc(stride * 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);
fread(reference, sizeof(u32), stride * h, bmp);
fclose(bmp);
}
else
@ -304,10 +335,10 @@ double CompareScreenshot(const u8 *pixels, int w, int h, int stride, const std::
}
u32 errors = 0;
for (int y = 0; y < h; ++y)
for (u32 y = 0; y < h; ++y)
{
for (int x = 0; x < w; ++x)
errors += ComparePixel(pixels32[y * stride + x], reference[y * w + x]);
for (u32 x = 0; x < w; ++x)
errors += ComparePixel(pixels[y * stride + x], reference[y * stride + x]);
}
free(reference);

@ -16,9 +16,12 @@
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
#include <string>
#include <vector>
#include "Globals.h"
struct GPUDebugBuffer;
extern bool teamCityMode;
extern std::string teamCityName;
void TeamCityPrint(const char *fmt, ...);
@ -28,4 +31,5 @@ std::string ExpectedScreenshotFromFilename(const std::string &bootFilename);
std::string GetTestName(const std::string &bootFilename);
bool CompareOutput(const std::string &bootFilename, const std::string &output, bool verbose);
double CompareScreenshot(const u8 *pixels, int w, int h, int stride, const std::string screenshotFilename, std::string &error);
std::vector<u32> TranslateDebugBufferToCompare(const GPUDebugBuffer *buffer, u32 stride, u32 h);
double CompareScreenshot(const std::vector<u32> &pixels, u32 stride, u32 w, u32 h, const std::string screenshotFilename, std::string &error);

@ -24,6 +24,7 @@
#include "Core/CoreParameter.h"
#include "Core/System.h"
#include "GPU/Common/GPUDebugInterface.h"
#include "base/logging.h"
#include "gfx_es2/gl_state.h"
@ -108,16 +109,16 @@ 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;
u8 *pixels = new u8[FRAME_WIDTH * FRAME_HEIGHT * 4];
const static u32 FRAME_STRIDE = 512;
const static u32 FRAME_WIDTH = 480;
const static u32 FRAME_HEIGHT = 272;
// TODO: Maybe this code should be moved into GLES_GPU to support DirectX/etc.
glReadBuffer(GL_FRONT);
glReadPixels(0, 0, FRAME_WIDTH, FRAME_HEIGHT, GL_BGRA, GL_UNSIGNED_BYTE, pixels);
GPUDebugBuffer buffer;
gpuDebug->GetCurrentFramebuffer(buffer);
const std::vector<u32> pixels = TranslateDebugBufferToCompare(&buffer, 512, 272);
std::string error;
double errors = CompareScreenshot(pixels, FRAME_WIDTH, FRAME_HEIGHT, FRAME_WIDTH, comparisonScreenshot, error);
double errors = CompareScreenshot(pixels, FRAME_STRIDE, FRAME_WIDTH, FRAME_HEIGHT, comparisonScreenshot, error);
if (errors < 0)
SendOrCollectDebugOutput(error);
@ -143,14 +144,12 @@ void WindowsHeadlessHost::SendDebugScreenshot(const u8 *pixbuf, u32 w, u32 h)
if (saved)
{
fwrite(&header, sizeof(header), 1, saved);
fwrite(pixels, sizeof(u32), FRAME_WIDTH * FRAME_HEIGHT, saved);
fwrite(pixels.data(), sizeof(u32), FRAME_STRIDE * FRAME_HEIGHT, saved);
fclose(saved);
SendOrCollectDebugOutput("Actual output written to: __testfailure.bmp\n");
}
}
delete [] pixels;
}
void WindowsHeadlessHost::SetComparisonScreenshot(const std::string &filename)