aboutsummaryrefslogtreecommitdiffhomepage
path: root/experimental/skpdiff/SkCLImageDiffer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'experimental/skpdiff/SkCLImageDiffer.cpp')
-rw-r--r--experimental/skpdiff/SkCLImageDiffer.cpp122
1 files changed, 122 insertions, 0 deletions
diff --git a/experimental/skpdiff/SkCLImageDiffer.cpp b/experimental/skpdiff/SkCLImageDiffer.cpp
new file mode 100644
index 0000000000..d1e6958ab9
--- /dev/null
+++ b/experimental/skpdiff/SkCLImageDiffer.cpp
@@ -0,0 +1,122 @@
+/*
+ * 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];
+ clGetProgramBuildInfo(program, fDevice, CL_PROGRAM_BUILD_LOG, sizeof(buildLog),
+ buildLog, NULL);
+ 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;
+}
+
+bool SkCLImageDiffer::makeImage2D(SkBitmap* bitmap, cl_mem* image) {
+ cl_int imageErr;
+ cl_image_format bitmapFormat;
+ switch (bitmap->config()) {
+ case SkBitmap::kA8_Config:
+ bitmapFormat.image_channel_order = CL_A;
+ bitmapFormat.image_channel_data_type = CL_UNSIGNED_INT8;
+ break;
+ case SkBitmap::kRGB_565_Config:
+ bitmapFormat.image_channel_order = CL_RGB;
+ bitmapFormat.image_channel_data_type = CL_UNORM_SHORT_565;
+ break;
+ case SkBitmap::kARGB_8888_Config:
+ 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;
+}