2013-06-14 17:26:54 +00:00
|
|
|
/*
|
|
|
|
* Copyright 2013 Google Inc.
|
|
|
|
*
|
|
|
|
* Use of this source code is governed by a BSD-style license that can be
|
|
|
|
* found in the LICENSE file.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <cstring>
|
|
|
|
|
|
|
|
#include "SkBitmap.h"
|
|
|
|
#include "SkStream.h"
|
|
|
|
|
|
|
|
#include "SkCLImageDiffer.h"
|
|
|
|
#include "skpdiff_util.h"
|
|
|
|
|
|
|
|
SkCLImageDiffer::SkCLImageDiffer() {
|
|
|
|
fIsGood = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool SkCLImageDiffer::init(cl_device_id device, cl_context context) {
|
|
|
|
fContext = context;
|
|
|
|
fDevice = device;
|
|
|
|
|
|
|
|
cl_int queueErr;
|
|
|
|
fCommandQueue = clCreateCommandQueue(fContext, fDevice, 0, &queueErr);
|
|
|
|
if (CL_SUCCESS != queueErr) {
|
|
|
|
SkDebugf("Command queue creation failed: %s\n", cl_error_to_string(queueErr));
|
|
|
|
fIsGood = false;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
fIsGood = this->onInit();
|
|
|
|
return fIsGood;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool SkCLImageDiffer::loadKernelFile(const char file[], const char name[], cl_kernel* kernel) {
|
|
|
|
// Open the kernel source file
|
|
|
|
SkFILEStream sourceStream(file);
|
|
|
|
if (!sourceStream.isValid()) {
|
|
|
|
SkDebugf("Failed to open kernel source file");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return loadKernelStream(&sourceStream, name, kernel);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool SkCLImageDiffer::loadKernelStream(SkStream* stream, const char name[], cl_kernel* kernel) {
|
|
|
|
// Read the kernel source into memory
|
|
|
|
SkString sourceString;
|
|
|
|
sourceString.resize(stream->getLength());
|
|
|
|
size_t bytesRead = stream->read(sourceString.writable_str(), sourceString.size());
|
|
|
|
if (bytesRead != sourceString.size()) {
|
|
|
|
SkDebugf("Failed to read kernel source file");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return loadKernelSource(sourceString.c_str(), name, kernel);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool SkCLImageDiffer::loadKernelSource(const char source[], const char name[], cl_kernel* kernel) {
|
|
|
|
// Build the kernel source
|
|
|
|
size_t sourceLen = strlen(source);
|
|
|
|
cl_program program = clCreateProgramWithSource(fContext, 1, &source, &sourceLen, NULL);
|
|
|
|
cl_int programErr = clBuildProgram(program, 1, &fDevice, "", NULL, NULL);
|
|
|
|
if (CL_SUCCESS != programErr) {
|
|
|
|
SkDebugf("Program creation failed: %s\n", cl_error_to_string(programErr));
|
|
|
|
|
|
|
|
// Attempt to get information about why the build failed
|
|
|
|
char buildLog[4096];
|
2013-06-28 16:27:33 +00:00
|
|
|
clGetProgramBuildInfo(program, fDevice, CL_PROGRAM_BUILD_LOG, sizeof(buildLog),
|
|
|
|
buildLog, NULL);
|
2013-06-14 17:26:54 +00:00
|
|
|
SkDebugf("Build log: %s\n", buildLog);
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
cl_int kernelErr;
|
|
|
|
*kernel = clCreateKernel(program, name, &kernelErr);
|
|
|
|
if (CL_SUCCESS != kernelErr) {
|
|
|
|
SkDebugf("Kernel creation failed: %s\n", cl_error_to_string(kernelErr));
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2013-11-12 18:29:17 +00:00
|
|
|
bool SkCLImageDiffer::makeImage2D(SkBitmap* bitmap, cl_mem* image) const {
|
2013-06-14 17:26:54 +00:00
|
|
|
cl_int imageErr;
|
|
|
|
cl_image_format bitmapFormat;
|
2014-06-14 12:30:20 +00:00
|
|
|
switch (bitmap->colorType()) {
|
|
|
|
case kAlpha_8_SkColorType:
|
2013-06-14 17:26:54 +00:00
|
|
|
bitmapFormat.image_channel_order = CL_A;
|
|
|
|
bitmapFormat.image_channel_data_type = CL_UNSIGNED_INT8;
|
|
|
|
break;
|
2014-06-14 12:30:20 +00:00
|
|
|
case kRGB_565_SkColorType:
|
2013-06-14 17:26:54 +00:00
|
|
|
bitmapFormat.image_channel_order = CL_RGB;
|
|
|
|
bitmapFormat.image_channel_data_type = CL_UNORM_SHORT_565;
|
|
|
|
break;
|
2014-06-14 12:30:20 +00:00
|
|
|
case kN32_SkColorType:
|
2013-06-14 17:26:54 +00:00
|
|
|
bitmapFormat.image_channel_order = CL_RGBA;
|
|
|
|
bitmapFormat.image_channel_data_type = CL_UNSIGNED_INT8;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
SkDebugf("Image format is unsupported\n");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Upload the bitmap data to OpenCL
|
|
|
|
bitmap->lockPixels();
|
|
|
|
*image = clCreateImage2D(fContext, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR,
|
|
|
|
&bitmapFormat, bitmap->width(), bitmap->height(),
|
|
|
|
bitmap->rowBytes(), bitmap->getPixels(),
|
|
|
|
&imageErr);
|
|
|
|
bitmap->unlockPixels();
|
|
|
|
|
|
|
|
if (CL_SUCCESS != imageErr) {
|
|
|
|
SkDebugf("Input image creation failed: %s\n", cl_error_to_string(imageErr));
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|