migrate skpdiff to tools

R=djsollen@google.com

Review URL: https://codereview.chromium.org/19671002

git-svn-id: http://skia.googlecode.com/svn/trunk@10225 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
zachr@google.com 2013-07-22 13:14:04 +00:00
parent 14cec91fe1
commit a54aaf7fba
22 changed files with 163 additions and 89 deletions

View File

@ -1,53 +0,0 @@
# GYP file to build skpdiff.
#
# To build on Linux:
# ./gyp_skia skpdiff.gyp && make skpdiff
#
{
'targets': [
{
'target_name': 'skpdiff',
'type': 'executable',
'sources': [
'main.cpp',
'SkDiffContext.cpp',
'SkImageDiffer.cpp',
'SkPMetric.cpp',
'skpdiff_util.cpp',
'../../tools/flags/SkCommandLineFlags.cpp',
],
'include_dirs': [
'../../tools/flags'
],
'dependencies': [
'../../gyp/skia_lib.gyp:skia_lib',
],
'cflags': [
'-O3',
],
'conditions': [
['skia_opencl', {
'sources': [
'SkCLImageDiffer.cpp',
'SkDifferentPixelsMetric_opencl.cpp',
],
'link_settings': {
'libraries': [
'-lOpenCL',
],
},
}, {
'sources': [
'SkDifferentPixelsMetric_cpu.cpp',
],
}],
],
},
],
}
# Local Variables:
# tab-width:2
# indent-tabs-mode:nil
# End:
# vim: set expandtab tabstop=2 shiftwidth=2:

View File

@ -21,6 +21,7 @@
'render_pdfs',
'render_pictures',
'skdiff',
'skpdiff',
'skhello',
'skimage',
],
@ -50,6 +51,54 @@
'skia_lib.gyp:skia_lib',
],
},
{
'target_name': 'skpdiff',
'type': 'executable',
'sources': [
'../tools/skpdiff/skpdiff_main.cpp',
'../tools/skpdiff/SkDiffContext.cpp',
'../tools/skpdiff/SkImageDiffer.cpp',
'../tools/skpdiff/SkPMetric.cpp',
'../tools/skpdiff/skpdiff_util.cpp',
'../tools/flags/SkCommandLineFlags.cpp',
],
'include_dirs': [
'../tools/flags'
],
'dependencies': [
'skia_lib.gyp:skia_lib',
],
'cflags': [
'-O3',
],
'conditions': [
['skia_opencl', {
'sources': [
'../tools/skpdiff/SkCLImageDiffer.cpp',
'../tools/skpdiff/SkDifferentPixelsMetric_opencl.cpp',
],
'conditions': [
[ 'skia_os == "mac"', {
'link_settings': {
'libraries': [
'$(SDKROOT)/System/Library/Frameworks/OpenCL.framework',
]
}
}, {
'link_settings': {
'libraries': [
'-lOpenCL',
],
},
}],
],
}, { # !skia_opencl
'sources': [
'../tools/skpdiff/SkDifferentPixelsMetric_cpu.cpp',
],
}],
],
},
{
'target_name': 'skimagediff',
'type': 'executable',

View File

@ -8,7 +8,11 @@
#ifndef SkCLImageDiffer_DEFINED
#define SkCLImageDiffer_DEFINED
#include <CL/cl.h>
#if SK_BUILD_FOR_MAC
# include <OpenCL/cl.h>
#else
# include <CL/cl.h>
#endif
#include "SkTDArray.h"
#include "SkImageDiffer.h"

View File

@ -180,7 +180,7 @@ void SkDiffContext::outputRecords(SkWStream& stream, bool useJSONP) {
stream.writeText("\",\n");
stream.writeText(" \"result\": ");
stream.writeScalarAsText(data.fResult);
stream.writeScalarAsText((SkScalar)data.fResult);
stream.writeText(",\n");
stream.writeText(" \"pointsOfInterest\": [\n");

View File

@ -22,7 +22,6 @@ static const char kDifferentPixelsKernelSource[] =
" int2 coord = (int2)(get_global_id(0), get_global_id(1)); \n"
" uint4 baselinePixel = read_imageui(baseline, gInSampler, coord); \n"
" uint4 testPixel = read_imageui(test, gInSampler, coord); \n"
" int4 pixelCompare = baselinePixel == testPixel; \n"
" if (baselinePixel.x != testPixel.x || \n"
" baselinePixel.y != testPixel.y || \n"
" baselinePixel.z != testPixel.z || \n"
@ -120,9 +119,12 @@ int SkDifferentPixelsMetric::queueDiff(SkBitmap* baseline, SkBitmap* test) {
diff->result *= (double)diff->numDiffPixels;
diff->result = (1.0 - diff->result);
diff->poi = SkNEW_ARRAY(SkIPoint, diff->numDiffPixels);
clEnqueueReadBuffer(fCommandQueue, diff->poiBuffer, CL_TRUE, 0,
// Reading a buffer of size zero can cause issues on some (Mac) OpenCL platforms.
if (diff->numDiffPixels > 0) {
diff->poi = SkNEW_ARRAY(SkIPoint, diff->numDiffPixels);
clEnqueueReadBuffer(fCommandQueue, diff->poiBuffer, CL_TRUE, 0,
sizeof(SkIPoint) * diff->numDiffPixels, diff->poi, 0, NULL, NULL);
}
// Release all the buffers created
clReleaseMemObject(diff->poiBuffer);

View File

@ -90,8 +90,7 @@ typedef ImageArray<float> ImageL3D;
#define MAT_ROW_MULT(rc,gc,bc) r*rc + g*gc + b*bc
void adobergb_to_cielab(float r, float g, float b, LAB* lab) {
static void adobergb_to_cielab(float r, float g, float b, LAB* lab) {
// Conversion of Adobe RGB to XYZ taken from from "Adobe RGB (1998) ColorImage Encoding"
// URL:http://www.adobe.com/digitalimag/pdfs/AdobeRGB1998.pdf
// Section: 4.3.5.3
@ -152,7 +151,7 @@ static void bitmap_to_cielab(const SkBitmap* bitmap, ImageLAB* outImageLAB) {
// From Barten SPIE 1989
static float contrast_sensitivity(float cyclesPerDegree, float luminance) {
float a = 440.0f * powf(1.0f + 0.7f / luminance, -0.2f);
float b = 0.3f * powf(1 + 100.0 / luminance, 0.15f);
float b = 0.3f * powf(1.0f + 100.0f / luminance, 0.15f);
return a *
cyclesPerDegree *
expf(-b * cyclesPerDegree) *
@ -259,14 +258,20 @@ static void convolve(const ImageL* imageL, bool vertical, ImageL* outImageL) {
}
}
float pmetric(const ImageLAB* baselineLAB, const ImageLAB* testLAB, SkTDArray<SkIPoint>* poi) {
static double pmetric(const ImageLAB* baselineLAB, const ImageLAB* testLAB, SkTDArray<SkIPoint>* poi) {
int width = baselineLAB->width;
int height = baselineLAB->height;
int maxLevels = (int)log2(width < height ? width : height);
int maxLevels = 0;
const float fov = M_PI / 180.0f * 45.0f;
// Calculates how many levels to make by how many times the image can be divided in two
int smallerDimension = width < height ? width : height;
for ( ; smallerDimension > 1; smallerDimension /= 2) {
maxLevels++;
}
const float fov = SK_ScalarPI / 180.0f * 45.0f;
float contrastSensitivityMax = contrast_sensitivity(3.248f, 100.0f);
float pixelsPerDegree = width / (2.0f * tanf(fov * 0.5f) * 180.0f / M_PI);
float pixelsPerDegree = width / (2.0f * tanf(fov * 0.5f) * 180.0f / SK_ScalarPI);
ImageL3D baselineL(width, height, maxLevels);
ImageL3D testL(width, height, maxLevels);
@ -326,8 +331,8 @@ float pmetric(const ImageLAB* baselineLAB, const ImageLAB* testLAB, SkTDArray<Sk
testL.getLayer(maxLevels - 1)->readPixel(x, y, &avgLTest);
float lAdapt = 0.5f * (avgLBaseline + avgLTest);
if (lAdapt < 1e-5) {
lAdapt = 1e-5;
if (lAdapt < 1e-5f) {
lAdapt = 1e-5f;
}
float contrastSum = 0.0f;
@ -352,15 +357,15 @@ float pmetric(const ImageLAB* baselineLAB, const ImageLAB* testLAB, SkTDArray<Sk
baselineContrast2 : testContrast2;
// Avoid divides by close to zero
if (denominator < 1e-5) {
denominator = 1e-5;
if (denominator < 1e-5f) {
denominator = 1e-5f;
}
contrast[levelIndex] = numerator / denominator;
contrastSum += contrast[levelIndex];
}
if (contrastSum < 1e-5) {
contrastSum = 1e-5;
if (contrastSum < 1e-5f) {
contrastSum = 1e-5f;
}
float F = 0.0f;

View File

@ -179,7 +179,7 @@ static float gCubeRootTable[] = {
0.9967341374f,0.9970616873f,0.9973890221f,0.9977161421f,0.9980430478f,0.9983697395f,
0.9986962176f,0.9990224823f,0.9993485340f,0.9996743731f,
};
float get_cube_root(float value) {
static float get_cube_root(float value) {
SkASSERT(value >= 0.0f);
SkASSERT(value * 1023.0f < 1024.0f);
return gCubeRootTable[(int)(value * 1023.0f)];
@ -230,7 +230,7 @@ static float gGammaTable[] = {
0.9239933353f,0.9322768503f,0.9406007070f,0.9489649382f,0.9573695762f,0.9658146535f,
0.9743002024f,0.9828262551f,0.9913928436f,1.0000000000f,
};
float get_gamma(unsigned char value) {
static float get_gamma(unsigned char value) {
return gGammaTable[value];
}
@ -1903,7 +1903,7 @@ static float gTVITable[] = {
5.5534835301f,5.5540394344f,5.5545953386f,5.5551512429f,5.5557071472f,5.5562630514f,
5.5568189557f,5.5573748599f,5.5579307642f,5.5584866684f,
};
float get_threshold_vs_intensity(float value) {
static float get_threshold_vs_intensity(float value) {
SkASSERT(value >= 0.0f);
SkASSERT(value < 100.0f);
return gTVITable[(int)(value * 100.0f)];
@ -2578,7 +2578,7 @@ static float gVisualMaskTable[] = {
331.9392982234f,331.9975309989f,332.0557593973f,332.1139834200f,332.1722030684f,332.2304183439f,
332.2886292480f,332.3468357821f,332.4050379475f,332.4632357458f,
};
float get_visual_mask(float value) {
static float get_visual_mask(float value) {
SkASSERT(value >= 0.0f);
SkASSERT(value < 4000.0f);
return gVisualMaskTable[(int)value];

View File

@ -60,7 +60,7 @@ def visual_mask(contrast):
# float gCubeRootTable[]
CUBE_ROOT_ACCESS_FUNCTION = '''
float get_cube_root(float value) {
static float get_cube_root(float value) {
SkASSERT(value >= 0.0f);
SkASSERT(value * 1023.0f < 1024.0f);
return gCubeRootTable[(int)(value * 1023.0f)];
@ -78,7 +78,7 @@ def generate_cube_root_table(stream):
# float gGammaTable[]
GAMMA_ACCESS_FUNCTION = '''
float get_gamma(unsigned char value) {
static float get_gamma(unsigned char value) {
return gGammaTable[value];
}
'''
@ -94,7 +94,7 @@ def generate_gamma_table(stream):
# float gTVITable[]
TVI_ACCESS_FUNCTION = '''
float get_threshold_vs_intensity(float value) {
static float get_threshold_vs_intensity(float value) {
SkASSERT(value >= 0.0f);
SkASSERT(value < 100.0f);
return gTVITable[(int)(value * 100.0f)];
@ -113,7 +113,7 @@ def generate_tvi_table(stream):
# float gVisualMaskTable[]
VISUAL_MASK_DOMAIN = 4000
VISUAL_MASK_ACCESS_FUNCTION = '''
float get_visual_mask(float value) {{
static float get_visual_mask(float value) {{
SkASSERT(value >= 0.0f);
SkASSERT(value < {}.0f);
return gVisualMaskTable[(int)value];

View File

@ -6,9 +6,16 @@
*/
#if SK_SUPPORT_OPENCL
#define __NO_STD_VECTOR // Uses cl::vectpr instead of std::vectpr
#define __NO_STD_STRING // Uses cl::STRING_CLASS instead of std::string
#include <CL/cl.hpp>
#if SK_BUILD_FOR_MAC
// Note that some macs don't have this header and it can be downloaded from the Khronos registry
# include <OpenCL/cl.hpp>
#else
# include <CL/cl.hpp>
#endif
#endif
#include "SkCommandLineFlags.h"
@ -35,7 +42,7 @@ DEFINE_bool(jsonp, true, "Output JSON with padding");
#if SK_SUPPORT_OPENCL
/// A callback for any OpenCL errors
CL_CALLBACK void error_notify(const char* errorInfo, const void* privateInfoSize, ::size_t cb, void* userData) {
static void CL_CALLBACK error_notify(const char* errorInfo, const void* privateInfoSize, ::size_t cb, void* userData) {
SkDebugf("OpenCL error notify: %s\n", errorInfo);
exit(1);
}
@ -55,8 +62,8 @@ static bool init_device_and_context(cl::Device* device, cl::Context* context) {
// Query for a device
cl::vector<cl::Device> deviceList;
platform.getDevices(CL_DEVICE_TYPE_GPU, &deviceList);
SkDebugf("The number of GPU devices is %u\n", deviceList.size());
platform.getDevices(CL_DEVICE_TYPE_ALL, &deviceList);
SkDebugf("The number of devices is %u\n", deviceList.size());
// Print some information about the device for debugging
*device = deviceList[0];

View File

@ -5,9 +5,16 @@
* found in the LICENSE file.
*/
#include <time.h>
#include <dirent.h>
#include <glob.h>
#if SK_BUILD_FOR_MAC || SK_BUILD_FOR_UNIX
# include <unistd.h>
# include <time.h>
# include <sys/time.h>
# include <dirent.h>
# include <glob.h>
#elif SK_BUILD_FOR_WIN32
# include <windows.h>
#endif
#include "SkOSFile.h"
#include "skpdiff_util.h"
@ -66,14 +73,27 @@ const char* cl_error_to_string(cl_int err) {
}
#endif
// TODO refactor BenchTimer to be used here
double get_seconds() {
#if defined(_POSIX_TIMERS) && defined(CLOCK_REALTIME)
struct timespec currentTime;
clock_gettime(CLOCK_REALTIME, &currentTime);
return currentTime.tv_sec + (double)currentTime.tv_nsec / 1e9;
#elif SK_BUILD_FOR_MAC || SK_BUILD_FOR_UNIX
struct timeval currentTime;
gettimeofday(&currentTime, NULL);
return currentTime.tv_sec + (double)currentTime.tv_usec / 1e6;
#elif SK_BUILD_FOR_WIN32
LARGE_INTEGER currentTime;
LARGE_INTEGER frequency;
QueryPerformanceCounter(&currentTime);
QueryPerformanceFrequency(&frequency);
return (double)currentTime.QuadPart / (double)frequency.QuadPart;
#endif
}
bool get_directory(const char path[], SkTArray<SkString>* entries) {
#if SK_BUILD_FOR_MAC || SK_BUILD_FOR_UNIX
// Open the directory and check for success
DIR* dir = opendir(path);
if (NULL == dir) {
@ -96,9 +116,41 @@ bool get_directory(const char path[], SkTArray<SkString>* entries) {
closedir(dir);
return true;
#elif SK_BUILD_FOR_WIN32
char pathDirGlob[MAX_PATH];
char pathLength = strlen(path);
strncpy(pathDirGlob, path, pathLength);
if (path[pathLength - 1] == '/' || path[pathLength - 1] == '\\') {
SkASSERT(pathLength + 2 <= MAX_PATH);
pathDirGlob[pathLength] = '*';
pathDirGlob[pathLength + 1] = '\0';
} else {
SkASSERT(pathLength + 3 <= MAX_PATH);
pathDirGlob[pathLength] = '\\';
pathDirGlob[pathLength + 1] = '*';
pathDirGlob[pathLength + 2] = '\0';
}
WIN32_FIND_DATA findFileData;
HANDLE hFind = FindFirstFile(pathDirGlob, &findFileData);
if (INVALID_HANDLE_VALUE == hFind) {
return false;
}
do {
if ((findFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0) {
entries->push_back(SkString(findFileData.cFileName));
}
} while (FindNextFile(hFind, &findFileData) != 0);
FindClose(hFind);
return true;
#endif
}
bool glob_files(const char globPattern[], SkTArray<SkString>* entries) {
#if SK_BUILD_FOR_MAC || SK_BUILD_FOR_UNIX
// TODO Make sure this works on windows. This may require use of FindNextFile windows function.
glob_t globBuffer;
if (glob(globPattern, 0, NULL, &globBuffer) != 0) {
@ -116,4 +168,7 @@ bool glob_files(const char globPattern[], SkTArray<SkString>* entries) {
globfree(&globBuffer);
return true;
#elif SK_BUILD_FOR_WIN32
return false;
#endif
}

View File

@ -12,7 +12,12 @@
#include "SkTArray.h"
#if SK_SUPPORT_OPENCL
#include <CL/cl.h>
#if SK_BUILD_FOR_MAC
# include <OpenCL/cl.h>
#else
# include <CL/cl.h>
#endif
/**
* Converts an OpenCL error number into the string of its enumeration name.
* @param err The OpenCL error number

View File

@ -60,4 +60,4 @@
<!-- Whatever template is used is rendered in the following div -->
<div ng-view></div>
</body>
</html>
</html>